<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lon Hosford</title>
	<atom:link href="http://www.lonhosford.com/lonblog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lonhosford.com/lonblog</link>
	<description>Digital Media Solutions Expert</description>
	<lastBuildDate>Mon, 01 Apr 2013 15:47:49 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5</generator>
		<item>
		<title>PhoneGap Cordova Accelerometer HTML5 Canvas Animation XCode Example</title>
		<link>http://www.lonhosford.com/lonblog/2012/04/12/phonegap-cordova-accelerometer-html5-canvas-animation-xcode-example/</link>
		<comments>http://www.lonhosford.com/lonblog/2012/04/12/phonegap-cordova-accelerometer-html5-canvas-animation-xcode-example/#comments</comments>
		<pubDate>Thu, 12 Apr 2012 17:56:30 +0000</pubDate>
		<dc:creator>Lon Hosford</dc:creator>
				<category><![CDATA[Cordova]]></category>
		<category><![CDATA[IPhone]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[XCode]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[HTML5 Canvas]]></category>

		<guid isPermaLink="false">http://www.lonhosford.com/lonblog/?p=2945</guid>
		<description><![CDATA[This is a template example using the accelerometer with Cordova or Phonegap and animating a sprite on the HTML5 canvas. I was working on a game using the html canvas and the accelerometer.  I developed a way to combine both in IOS using Objective C and the UIWebView in the UIKit. That approach limits distribution to the IOS platform but allows you to have all of the native UI items like screen navigation and just use the canvas for animations. ]]></description>
				<content:encoded><![CDATA[<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like http://www.lonhosford.com/lonblog/2012/04/12/phonegap-cordova-accelerometer-html5-canvas-animation-xcode-example/" send="true" width="450" show_faces="true" font=""></fb:like><!-- Place this tag where you want the +1 button to render --><br />
<g:plusone annotation="inline"></g:plusone></p>
<p>This is a template example using the accelerometer with Cordova or Phonegap and animating a sprite on the HTML5 canvas.<img class="alignleft" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/blog_image.png" alt="" width="160" height="218" /><br />
<div class="wp-caption alignright" style="width: 131px"><a href="http://www.amazon.com/gp/product/0321814290/ref=as_li_ss_il?ie=UTF8&#038;tag=hosfordusa&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0321814290" target="_blank"><img  src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&#038;Format=_SL160_&#038;ASIN=0321814290&#038;MarketPlace=US&#038;ID=AsinImage&#038;WS=1&#038;tag=hosfordusa&#038;ServiceVersion=20070822" alt="Learn cocos2D Game Development" width="121" height="160" class="  " title="PhoneGap Essentials: Building Cross-Platform Mobile Apps"/></a><p class="wp-caption-text">PhoneGap Essentials: Building Cross-Platform Mobile Apps</p></div> </p>
<p>I was working on a game using the html canvas and the accelerometer.  I developed a way to combine both in IOS using Objective C and the UIWebView in the UIKit. That approach limits distribution to the IOS platform but allows you to have all of the native UI items like screen navigation and just use the canvas for animations. </p>
<p>Then I became curious about distributing on multiple devices containing an accelerometer since the animation is being done in html canvas.  The solution was a hybrid mobile platform like Cordova. UI in Cordova is really up to you although you can find UI libraries written in HTML, JavaScript and JQuery optimized for mobile.</p>
<p>Here are screen shots for the app. </p>
<p><img width="489" height="240" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/screen_shots.png" class="aligncenter"></p>
<p>There is only one screen and these are just showing the animated red circle in different positions. The functionality is simple in that the red circle moves in the direction of the accelerometer&#8217;s x and y values &#8211; well with some adjustments but we will cover them in a bit. </p>
<p>When it reaches the boundaries of the canvas for either direction, it stop moving in that one direction. Thus you can move it to any corner and it will stay fixed and you can move it around the edges of the canvas.</p>
<p>You can also tap the canvas to start and stop the animation.<br />
<div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>The Project Files</strong></p>
<p>The project uses Cordova 1.6, XCode 4.3.2 and was tested using iOS 5.1 on a IPhone 4. </p>
<p>I had started the example using Cordova 1.5. Cordova 1.6 was released before completing this article and Cordova 1.6 changed the accelerometer values. The release notes included &#8220;Rewrite of accelerometer code and removed DeviceInfo old init approach&#8221; and &#8220;Added unification of accelerometer values on ios (based on android values)&#8221;. Boiling those entries down we get that the values are the same across platform, but if you are using IOS you better divide by 10. I commented in the code in case you are still using 1.5 or earlier.</p>
<p> I added a simple html console area to display debugging messages from the Javascript.</p>
<p>I also stripped out most of the extra Cordova comments that were not relevant to this example. </p>
<p><strong><a onclick="javascript: pageTracker._trackPageview('/downloads/xcode_cordova/accelerometer_html_canvas/'); " href="http://www.lonhosford.com/content/xcode_cordova/accelerometer_html_canvas/CordovaAccelerometerCanvas.zip">Download XCode Project Files</a></strong></p>
<p><strong>Step 1 &#8211; Install Cordova for XCode</strong></p>
<p>Instructions for setting up your development environment are located at the PhoneGap site <a href="http://docs.phonegap.com/en/1.5.0/guide_getting-started_ios_index.md.html#Getting%20Started%20with%20iOS">Getting Started with iOS</a>. </p>
<p><strong>Step 2 &#8211; Create New Cordova-based Application</strong></p>
<p><img width="618" height="406" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/new_project.jpg" class="aligncenter"></p>
<p><strong>Step 3 &#8211; Set XCode Project Options</strong></p>
<p><img width="538" height="460" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/new_project_options.png" class="aligncenter"><br />
Set the XCode project options as follows:</p>
<ul>
<li>Product name: Here I used CordovaAccelerometerCanvas as the project name. You can use a name of your own choosing.</li>
<li>Company identifier: Provide your own reverse domain name.</li>
<li>Use Automatic Reference Counting: <strong>Uncheck</strong></li>
</ul>
<p><strong>Step 4 &#8211; Choose A File Location</strong></p>
<p>Once you select a file location on your computer you will have a folder structure as follows:</p>
<p><img width="492" height="93" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/new_project_finder.png" class="aligncenter"></p>
<p>And in XCode you will see a project window as follows:</p>
<p><img width="302" height="495" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/new_project_xcode_project_explorer.png" class="aligncenter"></p>
<p>You may notice the project has a warning. Ignore this for now.</p>
<p><img width="348" height="71" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/new_project_status_warning.png" class="aligncenter"></p>
<p><strong>Step 5 &#8211; Create and Add the www Folder and Files to the Project</strong></p>
<p>These are the normal setup instructions for a Cordova alias PhoneGap XCode project. You can skip this step if you are used to creating Cordova XCode projects.</p>
<p>The process is creating a www folder by running the app once in the IPhone simulator and then add to the project explorer.</p>
<p>First run the app in the IPhone simulator.</p>
<p><img width="428" height="71" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/new_project_run_simulator.png" class="aligncenter"></p>
<p>The app runs but complains of the missing index.html file.</p>
<p><img width="366" height="716" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/new_project_simulator_error.png" class="aligncenter"></p>
<p>A www folder with this file and one other js file were created on your file system as this the app launched in the simulator. Here you see them and you need to drag the www folder into the Project Explorer. Do not drag to or copy to the XCode folders outside of XCode.</p>
<p><img width="635" height="620" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/drag_www.png" class="aligncenter"></p>
<p>Fill out the &#8220;Choose options for adding these files&#8221; dialog as follows.</p>
<p><img width="538" height="451" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/drag_www_add_options.png" class="aligncenter"></p>
<ul>
<li> Destination: Unchecked </li>
<li> Folders:  &#8220;Created folder references for added folders&#8221; selected.</li>
<li> Add to targets: CordovaAccelerometerCanvas checked.</li>
</ul>
<p>And here are the final results you see in the Project Explorer window.</p>
<p><img width="311" height="658" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/drag_www_project_explorer_complete.png" class="aligncenter"></p>
<p>Run the app in the IPhone simulator one more time.</p>
<p><img width="428" height="71" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/new_project_run_simulator.png" class="aligncenter"></p>
<p>This time you will be greeted with an Alert dialog with the &#8220;Cordova is working&#8221; message.</p>
<p><img width="370" height="716" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova/accelerometer_html_canvas/new_project_simulator_second_run.png" class="aligncenter"></p>
<p><strong>Step 7a &#8211; The Completed index.html File</strong></p>
<p>Here is the full index.html file completed for your copy convenience. Just replace your index.html file with this and you can test on your device. </p>
<p>I removed Cordova code comments and commented code not related to our needs that is included in the index.html file.</p>
<pre class="brush: jscript; collapse: true; light: false; title: ; toolbar: true; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;&lt;/title&gt;
        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;&quot; /&gt;
        &lt;meta charset=&quot;utf-8&quot;&gt;
        &lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot; src=&quot;cordova-1.6.0.js&quot;&gt;&lt;/script&gt;
        &lt;script type=&quot;text/javascript&quot;&gt;
            var console_log;                // Debugging div on device
            var canvas_ctx;                 // HTML canvas 2d context
            var SPEED = 10;                 // Canvas redraw speed in milliseconds and accelerometer frequency
            var DISTANCE_FACTOR = .1;       // Factor to adjust accelerometer values to screen distance. Cordova 1.6 changed to values to be Android compatible which appeared to be * 10. For Cordova 1.5 make this value 1.
            var ax = 0;                     // Acceleration x axis (Accelerometer value adjusted for direction)
            var ay = 0;                     // Acceleration y axis (Accelerometer value adjusted for direction)
            var x;                          // Circle x position
            var y;                          // Circle y position
            var vx = 0;                     // Velocity x axis
            var vy = 0;                     // Velocity y axis
            var WIDTH = 320;                // Width of canvas
            var HEIGHT = 300;               // Height of canvas
            var RADIUS = 50;                // Width of circle object
            var CIRCLE_COLOR = &quot;#f00&quot;;      // Circle color
            var CANVAS_COLOR = &quot;#FAF7F8&quot;;   // Color of canvas background
            var watchID;                    // Accelerometer.watchAcceleration return value. 
            var drawID;                     // Draw time interval. 
            var playing = true;             // Boolean if animation is playing.
            /* DOM body onload event callback */
            function onBodyLoad()
            {		
                document.addEventListener(&quot;deviceready&quot;, onDeviceReady, false);
            }
            /* Cordova has been initialized and is ready to roll */
            function onDeviceReady()
            {
                console.log('console_div');
                console_log = document.getElementById('console_div');
                console_log.innerHTML += &quot;onDeviceReady()&lt;br/&gt;&quot;;
                init();
            }
            /* Initialize canvas and animation */
            function init() 
            {
                var canvas = document.getElementById(&quot;canvas&quot;);
                canvas_ctx = canvas.getContext(&quot;2d&quot;);
                // Center 
                x = WIDTH / 2 ;
                y = HEIGHT/ 2 ;
                startPlay();
            }
            /* Start watching the accelerometer */
            function startWatch() 
            {
                var options = { frequency: SPEED };
                watchID = navigator.accelerometer.watchAcceleration(onSuccess, onError, options);
            }   
            // Stop watching the accelerometer
            function stopWatch() 
            {
                if (watchID) {
                    navigator.accelerometer.clearWatch(watchID);
                    watchID = null;
                }
            }
            /* Accelerometer data callback */
            function onSuccess( acceleration )
            {
                // Set drawing acceleration values
                ax = acceleration.x * DISTANCE_FACTOR * -1; // -1 to change direction for Cordova 1.6. Removed for Cordova 1.5.
                ay = acceleration.y * DISTANCE_FACTOR ;// Add * -1 for Cordova 1.5;
                // Optional ouput for understanding accelerator values.
                console_log.innerHTML = 
                'Acceleration X: ' + acceleration.x + '&lt;br /&gt;' +
                'Acceleration Y: ' + acceleration.y + '&lt;br /&gt;' +
                'Acceleration Z: ' + acceleration.z + '&lt;br /&gt;' +
                'Timestamp: '      + acceleration.timestamp ;
            }
            /*  Accelerometer error callback */
            function onError()
            {
                alert(&quot;Accelerometer Error&quot;);
            }
            /* Steps to start animation play */
            function startPlay()
            {
                playing = true;
                vx = 0;
                vy = 0;
                startWatch();
                drawID = setInterval(draw, SPEED);
            }
            /* Steps to stop animation play */
            function stopPlay()
            {
                clearInterval(drawID);
                stopWatch();
                playing = false;
            }
            /* Draw circle */   
            function circle( x, y, r ) 
            {
                canvas_ctx.beginPath();
                canvas_ctx.arc(x, y, r, 0, Math.PI*2, true);
                canvas_ctx.fill();
            }
            /* Draw rectangle */
            function rect( x, y, w, h ) 
            {
                canvas_ctx.beginPath();
                canvas_ctx.rect(x,y,w,h);
                canvas_ctx.closePath();
                canvas_ctx.fill();
            }
            /* Clear canvas */
            function clear() 
            {
                canvas_ctx.clearRect(0, 0, WIDTH, HEIGHT);
            }
            /* Compute drawing metrics and draw frame */    
            function draw() 
            {
                // Increase velocity by acceleration
                vx += ax;
                vy += ay;
                // Update circle drawing position.
                x += vx;
                y += vy;
                /* Boundaries testing */
                // Right boundary
                if ( x + RADIUS &gt; WIDTH  )
                {
                    x = WIDTH - RADIUS ;
                    vx = 0;
                }
                // Left boundary
                if (x - RADIUS  &lt;= 0)
                {
                    x = RADIUS   ;
                    vx = 0;
                }
                // Bottom boundary
                if (y +  RADIUS  &gt; HEIGHT)
                {
                    y = HEIGHT - RADIUS ;
                    vy = 0;
                }
                // Top boundary
                if (y - RADIUS  &lt;= 0)
                {
                    y = RADIUS  ;
                    vy = 0;
                }
                
                // Debugging info.
                //console_log.innerHTML = 
                //'x: ' + x + '&lt;br /&gt;' +
                //'y: ' + y + '&lt;br /&gt;' +
                //'vx: ' + vx + '&lt;br /&gt;' +
                //'vy: ' + vy + '&lt;br /&gt;' +
                //'ax: ' + ax + '&lt;br /&gt;' +
                //'ay: ' + ay + '&lt;br /&gt;' ;    
                
                /* Draw frame */
                // Clear canvas
                clear();
                // Draw canvas background
                canvas_ctx.fillStyle = CANVAS_COLOR;
                rect( 0, 0, WIDTH, HEIGHT );
                /* Draw circle */
                canvas_ctx.fillStyle = CIRCLE_COLOR;
                circle( x, y, RADIUS );
            }
            /* Canvas tag touch end event handler */
            function canvasTouchEnd()
            {
                if (playing)
                {
                    stopPlay();
                }
                else
                {
                    startPlay();
                }
            }
        &lt;/script&gt;
    &lt;/head&gt;
    &lt;body onload=&quot;onBodyLoad()&quot; style = &quot;text-align:center;background-color:#ccc;padding:0px;margin:0px;&quot;&gt;
        &lt;div&gt;
            &lt;h1 style = &quot;font-size:20px;margin-bottom:0px;margin-top:0px;padding-top:0px;&quot;&gt;Accelerometer + HTML5 Canvas&lt;/h1&gt;
            &lt;canvas id=&quot;canvas&quot; width=&quot;320&quot; height=&quot;300&quot; ontouchend = &quot;canvasTouchEnd();&quot; &gt;
                This text is displayed if your browser 
                does not support HTML5 Canvas.
            &lt;/canvas&gt;
            &lt;div id = &quot;console_div&quot; style = &quot;position:absolute;text-align:left;margin:2px;border:1px solid black;background-color:#fff;top:330px;left:0px;width:314px;height:118px;overflow:auto;&quot; 
                &gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>The remaining part of this article will explain the parts of the index.html file by topic.</p>
<p><strong>Step 7a &#8211; The index.html body Section</strong></p>
<p>Key in this section is the canvas tag on line 189. I am using the ontouchend event versus the onclick event to prevent a canvas flicker when the screen is touched. The action is to start and stop the animation.</p>
<p>Line 193 is my own html debugging console for simple examples. You should see the accelerometer values displayed in here when testing on a device.</p>
<pre class="brush: xml; first-line: 186; title: ; notranslate">
 &lt;body onload=&quot;onBodyLoad()&quot; style = &quot;text-align:center;background-color:#ccc;padding:0px;margin:0px;&quot;&gt;
        &lt;div&gt;
            &lt;h1 style = &quot;font-size:20px;margin-bottom:0px;margin-top:0px;padding-top:0px;&quot;&gt;Accelerometer + HTML5 Canvas&lt;/h1&gt;
            &lt;canvas id=&quot;canvas&quot; width=&quot;320&quot; height=&quot;300&quot; ontouchend = &quot;canvasTouchEnd();&quot; &gt;
                This text is displayed if your browser 
                does not support HTML5 Canvas.
            &lt;/canvas&gt;
            &lt;div id = &quot;console_div&quot; style = &quot;position:absolute;text-align:left;margin:2px;border:1px solid black;background-color:#fff;top:330px;left:0px;width:314px;height:118px;overflow:auto;&quot; 
                &gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/body&gt;
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>Step 7b &#8211; The index.html Accelerometer Code</strong></p>
<p>Cordova provides an <a href="http://docs.phonegap.com/en/1.6.0/cordova_accelerometer_accelerometer.md.html#Accelerometer" target = "_blank">api for the accelerometer</a>.  We use a good portion of it with this example.</p>
<p>The variables on lines 11 to 14 are helpers for the animation. We do not need them for raw access to the accelerometer. You can see their explanations and we will look at them applied further along.</p>
<pre class="brush: jscript; first-line: 11; title: ; notranslate">
            var SPEED = 10;                 // Canvas redraw speed in milliseconds and accelerometer frequency
            var DISTANCE_FACTOR = .1;       // Factor to adjust accelerometer values to screen distance. Cordova 1.6 changed to values to be Android compatible which appeared to be * 10. For Cordova 1.5 make this value 1.
            var ax = 0;                     // Acceleration x axis (Accelerometer value adjusted for direction)
            var ay = 0;                     // Acceleration y axis (Accelerometer value adjusted for direction)
</pre>
<p>Line 24 has an id for the accelerometer watch event. This can be used to clear the watch event when you do not need the accelerometer anymore.</p>
<pre class="brush: jscript; first-line: 24; title: ; notranslate">
            var watchID;                    // Accelerometer.watchAcceleration return value. 
</pre>
<p>I created the startWatch function for this example to call when we need to start collecting accelerometer data. </p>
<p>The accelerometer works by calling your own event handler functions using the <a href="http://docs.phonegap.com/en/1.6.0/cordova_accelerometer_accelerometer.md.html#accelerometer.watchAcceleration" target = "_blank">watchAcceleration</a> method you see on line 54.<br />
The <a href="http://docs.phonegap.com/en/1.6.0/cordova_accelerometer_accelerometer.md.html#accelerometer.watchAcceleration" target = "_blank">watchAcceleration</a> take a reference to your success and error handler as the first two arguments. </p>
<p>It also takes an options object for the third argument. Currently the only option object key is frequency measured in milliseconds. I am using the SPEED variable set to 10 milliseconds for the frequency. </p>
<p>The <a href="http://docs.phonegap.com/en/1.6.0/cordova_accelerometer_accelerometer.md.html#accelerometer.watchAcceleration" target = "_blank">watchAcceleration</a> returns an id so we can refer to it later. </p>
<pre class="brush: jscript; first-line: 50; title: ; notranslate">
            /* Start watching the accelerometer */
            function startWatch() 
            {
                var options = { frequency: SPEED };
                watchID = navigator.accelerometer.watchAcceleration(onSuccess, onError, options);
            }   
</pre>
<p>The stopWatch function is also created for the example to stop requesting accelerometer data anywhere in the code. Line 60 uses the <a href="http://docs.phonegap.com/en/1.6.0/cordova_accelerometer_accelerometer.md.html#accelerometer.clearWatch" target = "_blank">clearWatch</a> method to stop watching the accelerometer. The watchID variable from line 54 identifies the watch activity to end.</p>
<p>To prevent throwing errors, logic is included to test for the watchID.</p>
<pre class="brush: jscript; first-line: 56; title: ; notranslate">
            // Stop watching the accelerometer
            function stopWatch() 
            {
                if (watchID) {
                    navigator.accelerometer.clearWatch(watchID);
                    watchID = null;
                }
            }
</pre>
<p>The onSuccess function on line 64 is called from the <a href="http://docs.phonegap.com/en/1.6.0/cordova_accelerometer_accelerometer.md.html#accelerometer.watchAcceleration" target = "_blank">watchAcceleration</a> on line 54. </p>
<p>The onSuccess function passes an <a href="http://docs.phonegap.com/en/1.6.0/cordova_accelerometer_accelerometer.md.html#Acceleration" target = "_blank">acceleration object</a>. The acceleration object currently has four values and they are all displayed in our html console on line 71. </p>
<p>The other code in the onSuccess method prepares variables for the animation.</p>
<p>The ax and ay variables on line 68 and 69 are accelerometer x and y values respectively. They represent acceleration in our animation.</p>
<p>For the x-axis value we need to reverse the value sign so the tilt of the device represents the direction of the x-axis animation. Interesting this is for Cordova 1.6. In Cordova 1.5 this is not needed.</p>
<p>For the y-axis value we need to reverse the value sign if you are using Cordova 1.5. Again to represent the direction by the tilt of the device.</p>
<p>Finally the x and y acceleration values were adjusted with Cordova 1.6. As I had mentioned I started the example in Cordova 1.5 and was able to use the raw values. But with Cordova 1.6 the values are 10x so I added the DISTANCE_FACTOR variable set to .1 to compensate. Perhaps I should have called it a &#8220;VERSION_FACTOR&#8221;. </p>
<p>I had no need for z and timestamp properties in this example, but they are displayed for interest. You may get updates from the device due to your frequency of request, but the device has not sensed new values, so you can use the timestamp property in case you are using the accelerometer updates for a cpu intensive function that without a change is unnecessary.</p>
<pre class="brush: jscript; first-line: 64; title: ; notranslate">
            /* Accelerometer data callback */
            function onSuccess( acceleration )
            {
                // Set drawing acceleration values
                ax = acceleration.x * DISTANCE_FACTOR * -1; // -1 to change direction for Cordova 1.6. Removed for Cordova 1.5.
                ay = acceleration.y * DISTANCE_FACTOR ;// Add * -1 for Cordova 1.5;
                // Optional ouput for understanding accelerator values.
                console_log.innerHTML = 
                'Acceleration X: ' + acceleration.x + '&lt;br /&gt;' +
                'Acceleration Y: ' + acceleration.y + '&lt;br /&gt;' +
                'Acceleration Z: ' + acceleration.z + '&lt;br /&gt;' +
                'Timestamp: '      + acceleration.timestamp ;
            }
</pre>
<p>This final code snippet is simply the error handler for watching the accelerometer. Apparently there is no information provided for the error, so you will need to improvise.</p>
<pre class="brush: jscript; first-line: 77; title: ; notranslate">

            /*  Accelerometer error callback */
            function onError()
            {
                alert(&quot;Accelerometer Error&quot;);
            }
</pre>
<p><strong>Step 7c &#8211; User Start and Stop Interaction</strong></p>
<p>Touching the canvas starts and stops the animation. This starts on line 189 with the canvas tag ontouchend event calling the canvasTouchEnd() function on line 172.</p>
<pre class="brush: xml; first-line: 189; title: ; notranslate">
           &lt;canvas id=&quot;canvas&quot; width=&quot;320&quot; height=&quot;300&quot; ontouchend = &quot;canvasTouchEnd();&quot; &gt;
                This text is displayed if your browser 
                does not support HTML5 Canvas.
            &lt;/canvas&gt;
</pre>
<p>There is the playing variable set on line 26 that retains the state of animation playing.</p>
<pre class="brush: jscript; first-line: 26; title: ; notranslate">
            var playing = true;             // Boolean if animation is playing.
</pre>
<p>The canvasTouchEnd function uses the playing boolean variable to determine starting or stopping animation and calls function to handle changing the animation playing state. </p>
<pre class="brush: jscript; first-line: 172; title: ; notranslate">
            /* Canvas tag touch end event handler */
            function canvasTouchEnd()
            {
                if (playing)
                {
                    stopPlay();
                }
                else
                {
                    startPlay();
                }
            }
</pre>
<p>The startPlay function first sets the playing state to true.</p>
<p>To start playing the velocity variables are set to zero. This prevents any timing issues that may cause the animation move in a direction not indicative of the tilt of the device when the animation is restarted.</p>
<p>Receiving events from the accelerometer is started with the call to the startWatch function we reviewed earlier.</p>
<p>Handing the canvas redraw is done on line 89 with a JavaScript timer. The timing of the of the canvas redraw is the same as the updates from the accelerometer. You could consider a different design where the accelerometer updates perform the canvas redraw. However the approach we are using allows animations to occur that not dependent on the accelerometer changes should you need to add them. </p>
<pre class="brush: jscript; first-line: 82; title: ; notranslate">
            /* Steps to start animation play */
            function startPlay()
            {
                playing = true;
                vx = 0;
                vy = 0;
                startWatch();
                drawID = setInterval(draw, SPEED);
            }
</pre>
<p>Stopping animation is done by clearing the timer interval, stopping the accelerometer watching and setting the playing state to false.</p>
<pre class="brush: jscript; first-line: 92; title: ; notranslate">
            /* Steps to stop animation play */
            function stopPlay()
            {
                clearInterval(drawID);
                stopWatch();
                playing = false;
            }
</pre>
<p><strong>Step 7d &#8211; The index.html Canvas Animation</strong></p>
<p>The canvas animation does not require Cordova. It is just an interesting way to demonstrate using the accelerometer. All the animation in the canvas could be done in any HTML5 web browser.</p>
<p>First is the canvas tag which has a predefined width and height. We could create the canvas tag dynamically in JavaScript, but I left it out to keep code simpler. </p>
<pre class="brush: xml; first-line: 189; title: ; notranslate">
           &lt;canvas id=&quot;canvas&quot; width=&quot;320&quot; height=&quot;300&quot; ontouchend = &quot;canvasTouchEnd();&quot; &gt;
                This text is displayed if your browser 
                does not support HTML5 Canvas.
            &lt;/canvas&gt;
</pre>
<p>Next there are some variables that impact the canvas animation work. </p>
<p>Line 10 has a variable to reference the canvas 2d context to allow drawing. This will refer back to the canvas tag.</p>
<p>The SPEED variable on line 11 is for the JavaScript timer that will call the draw function. The draw function does all the work on the canvas.</p>
<p>Line 13 and 14 are acceleration values that are updated using the accelerometer. </p>
<p>The x and y on lines 14 and 15 are the position of the circle sprite we are animating.</p>
<p>The velocity variables are initialized to zero on lines 16 and 17.</p>
<p>Height and width of the canvas are repeated here for computing the boundaries for our animated circle sprite.</p>
<p>The diameter of the circle sprite is configurable on line 21</p>
<p>Adding some color on lines 22 and 23 for the circle sprite and background respectively.</p>
<p>Then we have on line 25 the  JavaScript timer interval id for redrawing the canvas.</p>
<pre class="brush: jscript; first-line: 9; title: ; notranslate">
            var console_log;                // Debugging div on device
            var canvas_ctx;                 // HTML canvas 2d context
            var SPEED = 10;                 // Canvas redraw speed in milliseconds and accelerometer frequency
            var DISTANCE_FACTOR = .1;       // Factor to adjust accelerometer values to screen distance. Cordova 1.6 changed to values to be Android compatible which appeared to be * 10. For Cordova 1.5 make this value 1.
            var ax = 0;                     // Acceleration x axis (Accelerometer value adjusted for direction)
            var ay = 0;                     // Acceleration y axis (Accelerometer value adjusted for direction)
            var x;                          // Circle x position
            var y;                          // Circle y position
            var vx = 0;                     // Velocity x axis
            var vy = 0;                     // Velocity y axis
            var WIDTH = 320;                // Width of canvas
            var HEIGHT = 300;               // Height of canvas
            var RADIUS = 50;                // Width of circle object
            var CIRCLE_COLOR = &quot;#f00&quot;;      // Circle color
            var CANVAS_COLOR = &quot;#FAF7F8&quot;;   // Color of canvas background
            var watchID;                    // Accelerometer.watchAcceleration return value. 
            var drawID;                     // Draw time interval. 
            var playing = true;             // Boolean if animation is playing.
</pre>
<p>The init() function is called when the app boots up and here you see on line 43 and 44 the standard way to get the drawing context to the canvas tag.</p>
<p>Also the starting position of the circle sprite is placed at the center of the screen. </p>
<pre class="brush: jscript; first-line: 40; title: ; notranslate">
            /* Initialize canvas and animation */
            function init() 
            {
                var canvas = document.getElementById(&quot;canvas&quot;);
                canvas_ctx = canvas.getContext(&quot;2d&quot;);
                // Center 
                x = WIDTH / 2 ;
                y = HEIGHT/ 2 ;
                startPlay();
            }
</pre>
<p>There are some utility functions for drawing shapes in the html canvas. First we have the circle method which demonstrates how to draw a circle given x, y and radius values.</p>
<p>Discussing the values for drawing on the canvas are beyond the scope of this article but I strongly suggest you get a copy of <a href="http://www.amazon.com/gp/product/1430236655/ref=as_li_ss_tl?ie=UTF8&#038;tag=hosfordusa&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1430236655">Foundation HTML5 Animation with JavaScript</a>.<img src="http://www.assoc-amazon.com/e/ir?t=hosfordusa&#038;l=as2&#038;o=1&#038;a=1430236655" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
<p>The values for the canvas 2d context arc method are centerX, centerY, radius, startingAngle in radians, endingAngle in radians and the boolean antiClockwise. </p>
<p>The startingAngle and endingAngle have radian values to draw a complete circle.</p>
<p>Note you will need to compensate for x and y because the values for x and y reference the center. You will see this offset in the boundary testing code.</p>
<pre class="brush: jscript; first-line: 98; title: ; notranslate">
            /* Draw circle */   
            function circle( x, y, r ) 
            {
                canvas_ctx.beginPath();
                canvas_ctx.arc(x, y, r, 0, Math.PI*2, true);
                canvas_ctx.fill();
            }
</pre>
<p>Next is the rect function on line 106 to draw a rectangle. The canvas 2d context rect method is straightforward drawing from top left corner of the rectangle. </p>
<pre class="brush: jscript; first-line: 106; title: ; notranslate">
            /* Draw rectangle */
            function rect( x, y, w, h ) 
            {
                canvas_ctx.beginPath();
                canvas_ctx.rect(x,y,w,h);
                canvas_ctx.closePath();
                canvas_ctx.fill();
            }
</pre>
<p>In drawing for animation, you will need to clear the canvas, so this clear function allows that to happen. The one line is clearRect method of the canvas 2d context. The clearRect method clears a rectangular area and here we have the entire canvas covered.</p>
<pre class="brush: jscript; first-line: 113; title: ; notranslate">

            /* Clear canvas */
            function clear() 
            {
                canvas_ctx.clearRect(0, 0, WIDTH, HEIGHT);
            }
</pre>
<p>The drawing position computations and actual drawing are both done in the draw function. Some animation applications you may want to split the drawing from the computations, but in this case putting them together meets our needs.</p>
<p>The velocity in the x and y directions are computed on lines 122 and 123. Simply they are increased or decreased by the change in acceleration values from the accelerometer. Acceleration values contain direction as well as acceleration.</p>
<p>Then we recompute the circle sprite position on lines 125 and 126.</p>
<p>Lines 127 &#8211; 151 are computing the boundaries for the canvas in relation to the proposed position of the center point, the x and y values, of the circle sprite. If any boundary is reached, then the velocity for that direction is set to zero and the position value is computed to keep the circle sprite in view at the edge.</p>
<p>I left the debugging information lines in but commented. If you use them, then comment lines 71 &#8211; 75.</p>
<p>Final work is to draw and this starts on line 164 where the canvas is cleared of all drawings.</p>
<p>Then lines 166 and 167 get our canvas background drawn.</p>
<p>The circle sprite is drawn on lines 169 and 170.</p>
<pre class="brush: jscript; first-line: 118; title: ; notranslate">
            /* Compute drawing metrics and draw frame */    
            function draw() 
            {
                // Increase velocity by acceleration
                vx += ax;
                vy += ay;
                // Update circle drawing position.
                x += vx;
                y += vy;
                /* Boundaries testing */
                // Right boundary
                if ( x + RADIUS &gt; WIDTH  )
                {
                    x = WIDTH - RADIUS ;
                    vx = 0;
                }
                // Left boundary
                if (x - RADIUS  &lt;= 0)
                {
                    x = RADIUS   ;
                    vx = 0;
                }
                // Bottom boundary
                if (y +  RADIUS  &gt; HEIGHT)
                {
                    y = HEIGHT - RADIUS ;
                    vy = 0;
                }
                // Top boundary
                if (y - RADIUS  &lt;= 0)
                {
                    y = RADIUS  ;
                    vy = 0;
                }
                
                // Debugging info.
                //console_log.innerHTML = 
                //'x: ' + x + '&lt;br /&gt;' +
                //'y: ' + y + '&lt;br /&gt;' +
                //'vx: ' + vx + '&lt;br /&gt;' +
                //'vy: ' + vy + '&lt;br /&gt;' +
                //'ax: ' + ax + '&lt;br /&gt;' +
                //'ay: ' + ay + '&lt;br /&gt;' ;    
                
                /* Draw frame */
                // Clear canvas
                clear();
                // Draw canvas background
                canvas_ctx.fillStyle = CANVAS_COLOR;
                rect( 0, 0, WIDTH, HEIGHT );
                /* Draw circle */
                canvas_ctx.fillStyle = CIRCLE_COLOR;
                circle( x, y, RADIUS );
            }
</pre>
<p>Good luck!<br />
<g:plusone annotation="inline"></g:plusone></p>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like href="http://www.lonhosford.com/lonblog/2012/04/12/phonegap-cordova-accelerometer-html5-canvas-animation-xcode-example/" send="true" width="450" show_faces="true" font=""></fb:like></p>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:comments href="http://www.lonhosford.com/lonblog/2012/04/12/phonegap-cordova-accelerometer-html5-canvas-animation-xcode-example/" num_posts="3" width="500"></fb:comments></p>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<!-- Place this render call where appropriate --><br />
<script type="text/javascript">
  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonhosford.com/lonblog/2012/04/12/phonegap-cordova-accelerometer-html5-canvas-animation-xcode-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PhoneGap Cordova Camera XCode Example</title>
		<link>http://www.lonhosford.com/lonblog/2012/04/07/phonegap-cordova-camera-xcode-example/</link>
		<comments>http://www.lonhosford.com/lonblog/2012/04/07/phonegap-cordova-camera-xcode-example/#comments</comments>
		<pubDate>Sat, 07 Apr 2012 18:17:14 +0000</pubDate>
		<dc:creator>Lon Hosford</dc:creator>
				<category><![CDATA[Cordova]]></category>
		<category><![CDATA[IPhone]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[XCode]]></category>
		<category><![CDATA[Camera]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[HTML5 Canvas]]></category>

		<guid isPermaLink="false">http://www.lonhosford.com/lonblog/?p=2871</guid>
		<description><![CDATA[This is a bare bones example of using Cordova or Phonegap to take a photo with your IPhone or IPad camera. The project uses XCode 4.3.2 and was tested using iOS 5.1 on a IPhone 4. There are no frills. I did make the button large enough for IPhone human guideline standards. I also added [...]]]></description>
				<content:encoded><![CDATA[<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like href="http://www.lonhosford.com/lonblog/2012/04/07/phonegap-cordova-camera-xcode-example/" send="true" width="450" show_faces="true" font=""></fb:like><!-- Place this tag where you want the +1 button to render --><br />
<g:plusone annotation="inline"></g:plusone></p>
<p>This is a bare bones example of using Cordova or Phonegap to take a photo with your IPhone or IPad camera.<img class="alignleft" src="http://www.lonhosford.com/images/xcode_cordova/cordova_camera.png" alt="" width="160" height="218" /><br />
<div class="wp-caption alignright" style="width: 131px"><a href="http://www.amazon.com/gp/product/0321814290/ref=as_li_ss_il?ie=UTF8&#038;tag=hosfordusa&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0321814290" target="_blank"><img  src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&#038;Format=_SL160_&#038;ASIN=0321814290&#038;MarketPlace=US&#038;ID=AsinImage&#038;WS=1&#038;tag=hosfordusa&#038;ServiceVersion=20070822" alt="Learn cocos2D Game Development" width="121" height="160" class="  " title="PhoneGap Essentials: Building Cross-Platform Mobile Apps"/></a><p class="wp-caption-text">PhoneGap Essentials: Building Cross-Platform Mobile Apps</p></div> </p>
<p>The project uses XCode 4.3.2 and was tested using iOS 5.1 on a IPhone 4. There are no frills. I did make the button large enough for IPhone human guideline standards. I also added a simple console area to display debugging messages from the Javascript.</p>
<p>I also stripped out most of the extra Cordova comments that were not relevant. </p>
<p>Each time you take a picture another file is added. This example does not provide a way to delete the files. If you remove the app from the phone, the images are deleted. You may need to study the  <a href="http://docs.phonegap.com/en/1.5.0/phonegap_file_file.md.html#File">Cordova File API</a> for how to manage your app&#8217;s local storage.</p>
<p>Here are the screens for the app. </p>
<p><img width="489" height="240" alt="" src="http://www.lonhosford.com/images/xcode_cordova/xcode_cordova_screen_shots.png" class="aligncenter"></p>
<p>The left screen is the app before any photo has been taken. It shows the integrated debugging console with the logged message that the Cordova onDeviceReady() method was called.</p>
<p>The middle screen is the IPhone Camera app with a photo just taken.</p>
<p>The right screen shows the app with a photo taken. You also see in the integrated console messages logged from the Javascript. The second line is the method called by touching the &#8220;Take Picture&#8221; button. The final message is the callback method from the Cordova getPicture camera method for a successful photo take. In particular you can see the file path and name of the photo.</p>
<p><strong><a onclick="javascript: pageTracker._trackPageview('/downloads/xcode_cordova/CordovaCamera.zip'); " href="http://www.lonhosford.com/content/xcode_cordova/CordovaCamera.zip">Download XCode Project Files</a></strong></p>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></p>
<p><strong>Step 1 &#8211; Install Cordova for XCode</strong></p>
<p>Instructions for setting up your development environment are located at the PhoneGap site <a href="http://docs.phonegap.com/en/1.5.0/guide_getting-started_ios_index.md.html#Getting%20Started%20with%20iOS">Getting Started with iOS</a>. </p>
<p><strong>Step 2 &#8211; Create New Cordova-based Application</strong></p>
<p><img width="618" height="406" alt="" src="http://www.lonhosford.com/images/xcode_cordova/xcode_cordova_new_project.jpg" class="aligncenter"></p>
<p><strong>Step 3 &#8211; Set XCode Project Options</strong></p>
<p><img width="540" height="460" alt="" src="http://www.lonhosford.com/images/xcode_cordova/xcode_cordova_new_project_options.jpg" class="aligncenter"><br />
Set the XCode project options as follows:</p>
<ul>
<li>Product name: Here I used CordovaCamera as the project name. You can use a name of your own choosing.</li>
<li>Company identifier: Provide your own reverse domain.</li>
<li>Use Automatic Reference Counting: <strong>Uncheck</strong></li>
</ul>
<p><strong>Step 4 &#8211; Choose A File Location</strong></p>
<p>Once you select a file location on your computer you will have a folder structure as follows:</p>
<p><img width="444" height="106" alt="" src="http://www.lonhosford.com/images/xcode_cordova/xcode_cordova_finder_create.jpg" class="aligncenter"></p>
<p>And in XCode you will see a project window as follows:</p>
<p><img width="261" height="478" alt="" src="http://www.lonhosford.com/images/xcode_cordova/xcode_cordova_project_explorer_create.jpg" class="aligncenter"></p>
<p>You may notice the project has a warning. Ignore this for now.</p>
<p><img width="358" height="75" alt="" src="http://www.lonhosford.com/images/xcode_cordova/xcode_cordova_project_status_create.jpg" class="aligncenter"></p>
<p><strong>Step 5 &#8211; Create and Add the www Folder and Files to the Project</strong></p>
<p>These are the normal setup instructions for a Cordova alias PhoneGap XCode project. You can skip this step if you are used to creating Cordova XCode projects.</p>
<p>The process is creating a www folder by running the app once in the IPhone simulator and then add to the project explorer.</p>
<p>First run the app in the IPhone simulator.</p>
<p><img width="431" height="74" alt="" src="http://www.lonhosford.com/images/xcode_cordova/xcode_cordova_run_iphone_simulator.jpg" class="aligncenter"></p>
<p>The app runs but complains of the missing index.html file.</p>
<p><img width="366" height="716" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova/xcode_cordova_simulator_first_run.png" class="aligncenter"></p>
<p>A www folder with this file and one other js file were created on your file system as this the app launched in the simulator. Here you see them and you need to drag the www folder into the Project Explorer. Do not drag to or copy to the XCode folders outside of XCode.</p>
<p><img width="556" height="624" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova/drag_www.png" class="aligncenter"></p>
<p>Fill out the &#8220;Choose options for adding these files&#8221; dialog as follows.</p>
<p><img width="539" height="453" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova/add_www_choose_options.png" class="aligncenter"></p>
<ul>
<li> Destination: Unchecked </li>
<li> Folders:  &#8220;Created folder references for added folders&#8221; selected.</li>
<li> Add to targets: CordovaCamera checked.</li>
</ul>
<p>And this is the final results you see in the Project Explorer window.</p>
<p><img width="260" height="543" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova/add_www_complete_project_explorer.png" class="aligncenter"></p>
<p>Run the app in the IPhone simulator one more time.</p>
<p><img width="431" height="74" alt="" src="http://www.lonhosford.com/images/xcode_cordova/xcode_cordova_run_iphone_simulator.jpg" class="aligncenter"></p>
<p>This time you will be greeted with an Alert dialog with the &#8220;Cordova is working&#8221; message.</p>
<p><img width="366" height="716" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova/xcode_cordova_simulator_second_run.png" class="aligncenter"></p>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></p>
<p><strong>Step 7 &#8211; Code the index.html File</strong></p>
<p>I removed code comments and commented code that is included in the index.html file.</p>
<p>Here is the full index.html file completed for your copy convenience. </p>
<pre class="brush: jscript; collapse: true; light: false; title: ; toolbar: true; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
  &lt;title&gt;Camera&lt;/title&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;&quot; /&gt;
	&lt;meta charset=&quot;utf-8&quot;&gt;
	&lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot; src=&quot;cordova-1.5.0.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    // Debugging div on device
    var console_log;
	
	function onBodyLoad()
	{		
		document.addEventListener(&quot;deviceready&quot;, onDeviceReady, false);
	}
	
	/*  Cordova has been initialized and is ready to roll */
	function onDeviceReady()
	{
        console_log = document.getElementById('console_div');
        console_log.innerHTML += &quot;onDeviceReady()&lt;br/&gt;&quot;;
	}
        
    /*  Open the device camera app */
    function capturePhoto() 
    {
        console_log.innerHTML += &quot;capturePhoto()&lt;br/&gt;&quot;;
        // navigator.camera.getPicture( cameraSuccess, cameraError, [ cameraOptions ] );
        navigator.camera.getPicture(getPhoto, 
                                    onFail, 
                                    { 
                                    quality: 50,
                                    destinationType: Camera.DestinationType.FILE_URI, // // Return image file URI
                                    sourceType:Camera.PictureSourceType.CAMERA,
                                    targetWidth:120,  // Width in pixels to scale image. Aspect ratio is maintained. Required targetHeight.
                                    targetHeight:180  // Height in pixels to scale image. Aspect ratio is maintained. Required targetWidth.
                                    });
    }
   /* navigator.camera.getPicture success function */
    function getPhoto(imageData) 
    {
        var cameraImage = document.getElementById('cameraImage');
        cameraImage.src = imageData;
        console_log.innerHTML += &quot;getPhoto() - cameraImage.src: &quot; + cameraImage.src + &quot;&lt;br/&gt;&quot;;
    }
    /* navigator.camera.getPicture fail function */
    function onFail(message) 
    {
        alert('Failed because: ' + message);
    }       
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body onload=&quot;onBodyLoad()&quot; style = &quot;text-align:center;background-color:#ccc;padding:0px;&quot;&gt;
      &lt;div&gt;
          &lt;h1 style = &quot;margin-bottom:0px;&quot;&gt;Cordova Camera&lt;/h1&gt;
          &lt;button style = &quot;font-size:20px;width:200px;height:44px;;margin-bottom:5px;&quot; onclick=&quot;capturePhoto();&quot;&gt;Take Picture&lt;/button&gt; 
          &lt;br&gt;
          &lt;img style=&quot;width:120px;height:180px;;background-color:#fff;&quot; id=&quot;cameraImage&quot; src=&quot;&quot; /&gt;
          &lt;div id=&quot;console_div&quot; style = &quot;text-align:left;border:1px solid black;background-color:#fff;height:150px;overflow:auto;&quot;&gt;&lt;/div&gt;
      &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>First look at the html starting on line 53. To simplify, the css is placed inline with tags versus the better approach of using an external css file.</p>
<pre class="brush: xml; first-line: 53; highlight: [54,55,56,57,58,59]; title: ; notranslate">
  &lt;body onload=&quot;onBodyLoad()&quot; style = &quot;text-align:center;background-color:#ccc;padding:0px;&quot;&gt;
      &lt;div&gt;
          &lt;h1 style = &quot;margin-bottom:0px;&quot;&gt;Cordova Camera&lt;/h1&gt;
          &lt;button style = &quot;font-size:20px;width:200px;height:44px;;margin-bottom:5px;&quot; onclick=&quot;capturePhoto();&quot;&gt;Take Picture&lt;/button&gt; 
          &lt;br&gt;
          &lt;img style=&quot;width:120px;height:180px;;background-color:#fff;&quot; id=&quot;cameraImage&quot; src=&quot;&quot; /&gt;
          &lt;div id=&quot;console_div&quot; style = &quot;text-align:left;border:1px solid black;background-color:#fff;height:150px;overflow:auto;&quot;&gt;&lt;/div&gt;
      &lt;/div&gt;
  &lt;/body&gt;
</pre>
<p>Line 54 is the container div. </p>
<p>Line 55 provides a simple page heading.</p>
<p>Line 56 is the &#8220;Take Picture&#8221; button. It calls the capturePhoto() method when touched. Notice that you use the onClick handler, Cordova does the translation to touch up event for you.</p>
<p>Line 57 is the img tag for the photo once we take a picture.</p>
<p>Line 58 is a debugging div for output from your javascript. There are other <a href="http://wiki.phonegap.com/w/page/16494768/Debugging%20PhoneGap%20Apps" target = "_blank">debugging console solutions</a> that may better serve your needs.</p>
<p>Back to the top of index.html, line 10 declares the console_log variable. It will globally reference the console_div div tag in the html. You can then see on lines 20 and 21 getting the reference from the DOM for console_div div tag.</p>
<pre class="brush: jscript; highlight: [9,10,14,20,21]; title: ; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
  &lt;title&gt;Camera&lt;/title&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;&quot; /&gt;
	&lt;meta charset=&quot;utf-8&quot;&gt;
	&lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot; src=&quot;cordova-1.5.0.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    // Debugging div on device
    var console_log;
	
	function onBodyLoad()
	{		
		document.addEventListener(&quot;deviceready&quot;, onDeviceReady, false);
	}
	
	/*  Cordova has been initialized and is ready to roll */
	function onDeviceReady()
	{
        console_log = document.getElementById('console_div');
        console_log.innerHTML += &quot;onDeviceReady()&lt;br/&gt;&quot;;
	}
</pre>
<p>The onBodyLoad function on line 12 is called from the DOM body tag onload event. It then provides a listener to the deviceready event from Cordova. </p>
<p>The deviceready event calls the onDeviceReady function to get the ball rolling. </p>
<p>This boot strapping is all standard for Cordova apps as it has since it was called PhoneGap.</p>
<p>Moving down to line 24 the capturePhoto function was added and is called by the &#8220;Take Picture&#8221; button in the html.</p>
<p>The function logs to our makeshift console on line 27. </p>
<p>The key item is the <a href="http://docs.phonegap.com/en/1.5.0/phonegap_camera_camera.md.html#Camera" target = "_blank">Cordova Camera API</a> being used on line 29.</p>
<p>You see the Cordova API is attached to the DOM navigator object.</p>
<p>In this case we are using the <a href="http://docs.phonegap.com/en/1.5.0/phonegap_camera_camera.md.html#camera.getPicture" target = "_blank">camera.getPicture method</a>. </p>
<p>The first argument is the function to call for a successful use of the device camera and the second is for failed usage of the device camera. </p>
<pre class="brush: jscript; first-line: 24; highlight: [27,29,30,31,32,33,34,35,36]; title: ; notranslate">
    /*  Open the device camera app */
    function capturePhoto() 
    {
        console_log.innerHTML += &quot;capturePhoto()&lt;br/&gt;&quot;;
        // navigator.camera.getPicture( cameraSuccess, cameraError, [ cameraOptions ] );
        navigator.camera.getPicture(getPhoto, 
                                    onFail, 
                                    { 
                                    quality: 50,
                                    destinationType: Camera.DestinationType.FILE_URI, // // Return image file URI
                                    sourceType:Camera.PictureSourceType.CAMERA,
                                    targetWidth:120,  // Width in pixels to scale image. Aspect ratio is maintained. Required targetHeight.
                                    targetHeight:180  // Height in pixels to scale image. Aspect ratio is maintained. Required targetWidth.
                                    });
    }
</pre>
<p>The details are in the third argument which is an array of properties called cameraOptions.</p>
<p>For the quality option on line 32 I choose the value of 50. This is a blatant copy from the documentation. But also I read that values over 50 may become a factor in memory issues. Something for you to research if you need a quality value over 50.</p>
<p>On line 33 the destinationType option takes values defined by Camera.DestinationType. </p>
<p>For the destinationType option I choose Camera.DestinationType.FILE_URI. The Camera.DestinationType.FILE_URI sends a file url of the picture taken to the success function. The only other choice for the destinationType property as of this writing is Camera.DestinationType.DATA_URL which returns an image as base64 encoded string to the success function. </p>
<p>Line 34 sets the sourceType option. It uses values from Camera.PictureSourceType. The official documentation leaves the sourceType option values up to your interpretation based on naming. The sourceType option I used is Camera.PictureSourceType.CAMERA since my plan is to use the device camera. The other two values are Camera.PictureSourceType.PHOTOLIBRARY and Camera.PictureSourceType.SAVEDPHOTOALBUM. </p>
<p>Finally on lines 35 and 36 I included the targetWidth and targetHeight options. </p>
<p>I found if you omit the targetWidth and targetHeight options you may have aspect ratio issues with displaying correct scaling. I discovered this when taking a picture using portrait and using landscape orientations in the camera app. The landscape orientation would have a distorted aspect ratio. </p>
<p>The html I set the img tag height and width to 120px and 180px respectively. As you see I used the same values for targetWidth and targetHeight respectively and that resolved my scaling issue. You see I copied the API documentation comments for these two options and added my own interpretation.</p>
<p>The last part of the javascript contains the navigator.camera.getPicture method success and fail functions named getPhoto and onFail respectively. </p>
<pre class="brush: jscript; first-line: 39; highlight: [40,42,43,49]; title: ; notranslate">
   /* navigator.camera.getPicture success function */
    function getPhoto(imageData) 
    {
        var cameraImage = document.getElementById('cameraImage');
        cameraImage.src = imageData;
        console_log.innerHTML += &quot;getPhoto() - cameraImage.src: &quot; + cameraImage.src + &quot;&lt;br/&gt;&quot;;
    }
    /* navigator.camera.getPicture fail function */
    function onFail(message) 
    {
        alert('Failed because: ' + message);
    }       
</pre>
<p>For getPhoto the image url is passed in the imageData argument in line 40. All is needed is to assign the url to img tag src property. In the html the img tag has the id of cameraImage and on line 42 we get a reference from the DOM and on line 43 the url assignment to the img tag is complete. </p>
<p>Line 44 displays the url in our makeshift console window for observation.</p>
<p>The navigator.camera.getPicture fail callback is the onFail function on line 47. Line 49 displays feedback using the argument which has a message. I have not yet hit a problem and do not know how to simulate one.</p>
<p><strong>Step 8 &#8211; Run the App</strong></p>
<p>When you run the app, you need to use your IPhone or IPad. The camera cannot be simulated. Here is the first screen. At the beginning of the blog are all the screens for your reference.</p>
<p><img width="320" height="480" style = "border-width:0px;" alt="" src="http://www.lonhosford.com/images/xcode_cordova//xcode_cordova_home_screen.png" class="aligncenter"></p>
<p>Good luck!<br />
<g:plusone annotation="inline"></g:plusone></p>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like href="http://www.lonhosford.com/lonblog/2012/04/07/phonegap-cordova-camera-xcode-example/" send="true" width="450" show_faces="true" font=""></fb:like></p>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:comments href="http://www.lonhosford.com/lonblog/2011/12/18/kobold2d-xcode-4-introduction-tutorial-lesson-1-basic-accelerometer/" num_posts="3" width="500"></fb:comments></p>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<!-- Place this render call where appropriate --><br />
<script type="text/javascript">
  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonhosford.com/lonblog/2012/04/07/phonegap-cordova-camera-xcode-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tap, Move, Shake: Turning Your Game Ideas into iPhone &amp; iPad Apps</title>
		<link>http://www.lonhosford.com/lonblog/2012/01/22/tap-move-shake-turning-your-game-ideas-into-iphone-ipad-apps/</link>
		<comments>http://www.lonhosford.com/lonblog/2012/01/22/tap-move-shake-turning-your-game-ideas-into-iphone-ipad-apps/#comments</comments>
		<pubDate>Sun, 22 Jan 2012 21:51:10 +0000</pubDate>
		<dc:creator>Lon Hosford</dc:creator>
				<category><![CDATA[Gaming]]></category>
		<category><![CDATA[IPhone]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://www.lonhosford.com/lonblog/?p=2845</guid>
		<description><![CDATA[Todd Moore&#8217;s new book, Tap, Move, Shake: Turning Your Game Ideas into iPhone &#038; iPad Apps, is currently the best choice for getting started with writing and publishing IOS games. A key feature is that the apps in the book are IN THE APP STORE. Never saw that trick before and I think is a [...]]]></description>
				<content:encoded><![CDATA[<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like href="http://www.lonhosford.com/lonblog/2012/01/22/tap-move-shake-turning-your-game-ideas-into-iphone-ipad-apps/" send="true" width="450" show_faces="true" font=""></fb:like><!-- Place this tag where you want the +1 button to render --><br />
<g:plusone annotation="inline"></g:plusone></p>
<p>Todd Moore&#8217;s new book, <strong><a href="http://www.amazon.com/gp/product/1449303455/ref=as_li_ss_tl?ie=UTF8&#038;tag=hosfordusa&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1449303455">Tap, Move, Shake: Turning Your Game Ideas into iPhone &#038; iPad Apps</a></strong>, is currently the best choice for getting started with writing and publishing IOS games. </p>
<p>A key feature is that <strong>the apps in the book are IN THE APP STORE</strong>. Never saw that trick before and I think is a standard for anyone writing IOS books. I actually followed the steps of creating an app I could download suffice it had a tad more flash in the store.</p>
<div class="wp-caption alignleft" style="width: 131px"><a href="http://www.amazon.com/gp/product/1449303455/ref=as_li_ss_tl?ie=UTF8&#038;tag=hosfordusa&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1449303455" target="_blank"><img  src="http://ecx.images-amazon.com/images/I/51erZvLUPaL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA300_SH20_OU01_.jpg" alt="Tap, Move, Shake: Turning Your Game Ideas into iPhone &#038; iPad Apps" width="121" height="160" class="  " title="Tap, Move, Shake: Turning Your Game Ideas into iPhone &#038; iPad Apps"/></a><p class="wp-caption-text">Tap, Move, Shake: Turning Your Game Ideas into iPhone &#038; iPad Apps</p></div>
<p>This is the first book I have seen in XCode/ObjectiveC that takes the submission to the App store as important a learning step as is the process of writing code. I loved the give and take App store rejection emails that provided a lot of insight for anyone who is going to submit an app the first time.</p>
<p>Also insightful is the special effort in giving the coder who is light on media creation great chapters on creating graphics and sound. Links provided are well researched.</p>
<p>On the wish list for me was not to dismiss ARC (Automatic Reference Counting) at the onset. Gee the book kinda assumes the beginner and ARC leans to that. But I suspect a case of examples completed at a time Apple was busy upsetting the cart for writers in progress.</p>
<p>The chapters are extremely well thought out especially the progression of development with the sections in each chapter. </p>
<p>I think you need a basic skill in XCode and Objective C to follow the book. XCode is introduced nicely for beginners and Objective C is learned more by example and less by explanation. I could not have solved some bugs without a basic skill in Objective C. The architecture of IOS app is explained well. I loved the clarity of explaining the bootstrap of an IOS app. I finally got it!</p>
<p>The book covers EVERYTHING you need from setting up for development, coding, basic testing, resource creation, app submission and even app marketing. All at a very clear to the point approach. The book examples make you feel you are starting at the beginning because they are from the gaming industry beginnings tuned to the phone.</p>
<p>This is 254 page book that has a good number of images taking up pages. Compared to 3 and 4 inch opus magnum IOS books out there that are OMGs difficult to hold open on the desk or in a lounge chair, Todd gets a great deal done as a focused writer. Cutting content is key. I rather buy more books than have big monsters.</p>
<p>Want to get started in IOS gaming without a gaming engine or better understand your gaming engine, then do this book.</p>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like href="http://www.lonhosford.com/lonblog/2012/01/22/tap-move-shake-turning-your-game-ideas-into-iphone-ipad-apps/" send="true" width="450" show_faces="true" font=""></fb:like></p>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:comments href="http://www.lonhosford.com/lonblog/2012/01/22/tap-move-shake-turning-your-game-ideas-into-iphone-ipad-apps/" num_posts="3" width="500"></fb:comments></p>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<!-- Place this render call where appropriate --><br />
<script type="text/javascript">
  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonhosford.com/lonblog/2012/01/22/tap-move-shake-turning-your-game-ideas-into-iphone-ipad-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kobold2D XCode 4 Introduction Tutorial Lesson 7 &#8211; Display Score Using Graphic Glyphs</title>
		<link>http://www.lonhosford.com/lonblog/2011/12/27/kobold2d-xcode-4-introduction-tutorial-lesson-7-display-score-using-graphic-glyphs/</link>
		<comments>http://www.lonhosford.com/lonblog/2011/12/27/kobold2d-xcode-4-introduction-tutorial-lesson-7-display-score-using-graphic-glyphs/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 16:17:54 +0000</pubDate>
		<dc:creator>Lon Hosford</dc:creator>
				<category><![CDATA[Kobold2D]]></category>
		<category><![CDATA[Accelerometer]]></category>
		<category><![CDATA[Cocos2d]]></category>
		<category><![CDATA[Gaming]]></category>

		<guid isPermaLink="false">http://www.lonhosford.com/lonblog/?p=2797</guid>
		<description><![CDATA[&#60;== Lesson 6 &#124;&#124; Lesson 8 ==&#62; The scoring in this game needs a display. Up to this point you can only see the score in the XCode console window. The scoring data you are tracking is the number of attempts and the number of hits. The number of attempts is a class property that [...]]]></description>
				<content:encoded><![CDATA[<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like href="http://www.lonhosford.com/lonblog/2011/12/18/kobold2d-xcode-4-introduction-tutorial-lesson-1-basic-accelerometer/" send="true" width="450" show_faces="true" font=""></fb:like><!-- Place this tag where you want the +1 button to render --><br />
<g:plusone annotation="inline"></g:plusone></p>
<p><a href="http://www.lonhosford.com/lonblog/2011/12/23/kobold2d-xcode-4-introduction-tutorial-lesson-6-add-collision-sound-effect/">&lt;== Lesson 6</a> || <a href="#" onclick = "alert('12/27/11: Lesson 8 - Add Levels\nIN PROGRESS. CHECK BACK LATER');return false">Lesson 8 ==&gt; </a>  </p>
<p>The scoring in this game needs a display. Up to this point you can only see the score in the XCode console window. <img class="alignleft" src="http://www.lonhosford.com/images/kobold2d/common/blog_article.png" alt="" width="160" height="218" /><br />
<div class="wp-caption alignright" style="width: 131px"><a href="http://www.amazon.com/gp/product/1430238135/ref=as_li_ss_tl?ie=UTF8&#038;tag=hosfordusa&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1430238135" target="_blank"><img  src="https://images-na.ssl-images-amazon.com/images/I/415NHKs30yL._SL160_.jpg" alt="Learn cocos2D Game Development" width="121" height="160" class="  " title="Learn cocos2D Game Development"/></a><p class="wp-caption-text">Learn cocos2D Game Development</p></div> </p>
<p>The scoring data you are tracking is the number of attempts and the number of hits. The number of attempts is a class property that increments each time a new moving target is started from the top of the screen.</p>
<p>The number of hits is incremented each time the player intercepts the moving target. </p>
<p>Using the number of attempts and number of hits, we can display three values. One is the total attempts. The second is the number of misses which is the number of hits minus the number of misses. The third value is the number of hits. </p>
<p>We will just display them at the top middle of the screen with a colon separating each value. </p>
<p>For the score display, we will use a graphic containing the exact characters we need. Those characters are the digits 0 to 9, a space and a colon. </p>
<div class="wp-caption aligncenter" style="width: 560px"><img class=" " style="border: 0pt none;" src="http://www.lonhosford.com/images/kobold2d/lesson_07/ipad_running.png" alt="" width="550" height="423" /><p class="wp-caption-text">Finished Lesson Running on IPad2 Simulator</p></div>
<p>To display the graphic characters you will use the Cocos2D <a href="http://www.cocos2d-iphone.org/api-ref/latest-stable/interface_c_c_label_b_m_font.html" target = _blank">CCLabelBMFont</a> class. You can pack all the characters into one file. Then the CCLabelBMFont treats each character like a <a href="http://www.cocos2d-iphone.org/api-ref/latest-stable/interface_c_c_sprite.html" target = _blank">CCSprite</a>. This means that each individual character can be rotated, scaled, translated, and tinted like other Cocos2D CCSprite objects. We do not have much more of a need other than to place them on the screen and layer them underneath the game pieces.</p>
<p><a href="http://glyphdesigner.71squared.com/" target = _blank">Glyph Designer</a> is the tool I use to create the files needed for <a href="http://www.cocos2d-iphone.org/api-ref/latest-stable/interface_c_c_label_b_m_font.html" target = _blank">CCLabelBMFont</a>. There is a fee for Glyph Designer. I have not used another tool like it but the $30 US was a great value and the online tutorial videos made getting use out of it a snap. Plus Cocos2D is a product Glyph Designer supports.</p>
<p><strong>Lesson Downloads</strong></p>
<ol>
<li>
<a onclick="javascript: pageTracker._trackPageview('/downloads/kobold2d/intro_tutorial/lesson07/introduction_tutorial_lesson07_assets.zip'); " href="http://www.lonhosford.com/content/kobold2d/intro_tutorial/lesson07/introduction_tutorial_lesson07_assets.zip">Game piece images, score glyph files including Glyph Designer project file and sound for project</a>.</li>
<li>
<a onclick="javascript: pageTracker._trackPageview('/downloads/kobold2d/intro_tutorial/lesson07/introduction_tutorial_common.zip'); " href="http://www.lonhosford.com/content/kobold2d/intro_tutorial/lesson07/introduction_tutorial_common.zip">IPhone images for project</a>. Icons and splash screen.</li>
<li>
<a onclick="javascript: pageTracker._trackPageview('/downloads/kobold2d/intro_tutorial/lesson07/Intro_Tutorial_Lesson_07.zip'); " href="http://www.lonhosford.com/content/kobold2d/intro_tutorial/lesson07/Intro_Tutorial_Lesson_07.zip">Completed Project</a>. This is built in Kobold2d 1.0.1.</li>
</ol>
<p><strong>Step 1 &#8211; Build an Empty-Project Template</strong></p>
<p>You can continue with the <a href="http://www.lonhosford.com/lonblog/2011/12/23/kobold2d-xcode-4-introduction-tutorial-lesson-6-add-collision-sound-effect/">Lesson 6</a> project and make changes noted here. <div class="wp-caption alignleft" style="width: 221px"><img class=" " style="border: 0pt none;" src="http://www.lonhosford.com/images/kobold2d/lesson_07/project_files_resources.png" alt="" width="211" height="303" /><p class="wp-caption-text">Listing of Projectfiles->Resources Group</p></div></p>
<p>Otherwise the steps for creating this project from an Empty-Project template are the same as <a href="http://www.lonhosford.com/lonblog/2011/12/18/kobold2d-xcode-4-introduction-tutorial-lesson-1-basic-accelerometer/">Lesson 1</a> except to substitute Lesson 7 for Lesson 1 in the project name and to include the red_ball.png, red_ball-hd.png and explosion.caf files when you add the game pieces. The explosion.caf goes in same group as the images. Then you can use the code presented here.</p>
<p>In either case your Projectfiles->Resources group should have the files shown in the image to the left.</p>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></p>
<p><strong>Step 2 &#8211; Set Properties in config.lua</strong></p>
<p>There are no new configuration properties from Lesson 6. Complete config.lua file is included here for your copy convenience.</p>
<pre class="brush: jscript; collapse: true; light: false; title: ; toolbar: true; notranslate">
--[[
* Kobold2D™ --- http://www.kobold2d.org
*
* Copyright (c) 2010-2011 Steffen Itterheim. 
* Released under MIT License in Germany (LICENSE-Kobold2D.txt).
--]]


--[[
* Need help with the KKStartupConfig settings?
* ------ http://www.kobold2d.com/x/ygMO ------
--]]


local config =
{
    KKStartupConfig = 
    {
        -- load first scene from a class with this name, or from a Lua script with this name with .lua appended
        FirstSceneClassName = &quot;GameLayer&quot;,

        -- set the director type, and the fallback in case the first isn't available
        DirectorType = DirectorType.DisplayLink,
        DirectorTypeFallback = DirectorType.NSTimer,

        MaxFrameRate = 60,
        DisplayFPS = YES,

        EnableUserInteraction = YES,
        EnableMultiTouch = NO,

        -- Render settings
        DefaultTexturePixelFormat = TexturePixelFormat.RGBA8888,
        GLViewColorFormat = GLViewColorFormat.RGB565,
        GLViewDepthFormat = GLViewDepthFormat.DepthNone,
        GLViewMultiSampling = NO,
        GLViewNumberOfSamples = 0,

        Enable2DProjection = NO,
        EnableRetinaDisplaySupport = YES,
        EnableGLViewNodeHitTesting = NO,
        EnableStatusBar = NO,

        -- Orientation &amp; Autorotation
        DeviceOrientation = DeviceOrientation.LandscapeLeft,
        AutorotationType = Autorotation.None,
        ShouldAutorotateToLandscapeOrientations = NO,
        ShouldAutorotateToPortraitOrientations = NO,
        AllowAutorotateOnFirstAndSecondGenerationDevices = NO,

        -- Ad setup
        EnableAdBanner = NO,
        PlaceBannerOnBottom = YES,
        LoadOnlyPortraitBanners = NO,
        LoadOnlyLandscapeBanners = NO,
        AdProviders = &quot;iAd, AdMob&quot;,	-- comma seperated list -&gt; &quot;iAd, AdMob&quot; means: use iAd if available, otherwise AdMob
        AdMobRefreshRate = 15,
        AdMobFirstAdDelay = 5,
        AdMobPublisherID = &quot;YOUR_ADMOB_PUBLISHER_ID&quot;, -- how to get an AdMob Publisher ID: http://developer.admob.com/wiki/PublisherSetup
        AdMobTestMode = YES,

        -- Mac OS specific settings
        AutoScale = NO,
        AcceptsMouseMovedEvents = NO,
        WindowFrame = RectMake(1024-640, 768-480, 640, 480),
        EnableFullScreen = NO,
    },
}

return config
</pre>
<p><strong>Step 3 &#8211; GameLayer.h </strong></p>
<p>Line 18 shows the  <a href="http://www.cocos2d-iphone.org/api-ref/latest-stable/interface_c_c_label_b_m_font.html" target = _blank">CCLabelBMFont</a> object for displaying the score.</p>
<pre class="brush: objc; highlight: [18]; title: ; notranslate">
/*
 * Kobold2D™ --- http://www.kobold2d.org
 *
 * Copyright (c) 2010-2011 Steffen Itterheim. 
 * Released under MIT License in Germany (LICENSE-Kobold2D.txt).
 */

#import &quot;kobold2d.h&quot;

@interface GameLayer : CCLayer
{
    CCSprite* player;
    CGPoint playerVelocity;
    CCSprite* movingTarget;
	float movingTargetMoveDuration;
    int totalAttempts;
    int totalHits;
    CCLabelBMFont* scoreLabel;
}
@end
</pre>
<p><strong>Step 4 &#8211; GameLayer.m: Add initScore and setScore Methods for Score Display</strong></p>
<p>Complete GameLayer.m file is included here for your copy convenience. </p>
<pre class="brush: objc; collapse: true; light: false; title: ; toolbar: true; notranslate">
/*
 * Kobold2D™ --- http://www.kobold2d.org
 *
 * Copyright (c) 2010-2011 Steffen Itterheim. 
 * Released under MIT License in Germany (LICENSE-Kobold2D.txt).
 */

#import &quot;GameLayer.h&quot;
#import &quot;SimpleAudioEngine.h&quot;

@interface GameLayer (PrivateMethods)
-(void) initMovingTarget;
-(void) movingTargetUpdate:(ccTime)delta;
-(void) startMovingTargetSequence;
-(void) endMovingTargetSequence;
-(void) checkForCollision;
-(void) initScore;
-(void) setScore;
@end

// Velocity deceleration
const float deceleration = 0.4f;
// Accelerometer sensitivity (higher = more sensitive)
const float sensitivity = 6.0f;
// Maximum velocity
const float maxVelocity = 100.0f;

@implementation GameLayer

-(id) init
{
	if ((self = [super init]))
	{
        // Enable accelerometer input events.
		[KKInput sharedInput].accelerometerActive = YES;
		[KKInput sharedInput].acceleration.filteringFactor = 0.2f;
        // Preload the sound effect into memory so there's no delay when playing it the first time.
		[[SimpleAudioEngine sharedEngine] preloadEffect:@&quot;explosion.caf&quot;];
        // Initialize the total attempts to hit a moving target.
        totalAttempts = 0;
        // Initialize the total hits
        totalHits = 0;
        // Graphic for player
        player = [CCSprite spriteWithFile:@&quot;green_ball.png&quot;];
		[self addChild:player z:0 tag:1];
        // Position player        
        CGSize screenSize = [[CCDirector sharedDirector] winSize];
		float imageHeight = [player texture].contentSize.height;
		player.position = CGPointMake(screenSize.width / 2, imageHeight / 2);
		glClearColor(0.1f, 0.1f, 0.3f, 1.0f);
		// First line of title
		CCLabelTTF* label = [CCLabelTTF labelWithString:@&quot;Kobold2d Intro Tutorial&quot; 
                                               fontName:@&quot;Arial&quot;  
                                               fontSize:30];
		label.position = [CCDirector sharedDirector].screenCenter;
		label.color = ccCYAN;
        [self addChild:label z:-1];
        // Second line of title
 		CCLabelTTF* label2 = [CCLabelTTF labelWithString:@&quot;Lesson 7&quot;
                                                fontName:@&quot;Arial&quot;
                                                fontSize:24];
		label2.color = ccCYAN;
        label2.position = CGPointMake([CCDirector sharedDirector].screenCenter.x ,label.position.y - label.boundingBox.size.height);
        [self addChild:label2 z:-1];
        // The score label initialized
        [self initScore];
        // Add below game action
		[self addChild:scoreLabel z:-1];
        // Seed random number generator
        srandom((UInt32)time(NULL));
        // Initialize our moving target.
        [self initMovingTarget];
        // Start animation -  the update method is called.
        [self scheduleUpdate];;
	}
	return self;
}
-(void) dealloc
{
#ifndef KK_ARC_ENABLED
	[super dealloc];
#endif // KK_ARC_ENABLED
}
#pragma mark Player Movement
-(void) acceleratePlayerWithX:(double)xAcceleration
{
    // Adjust velocity based on current accelerometer acceleration
    playerVelocity.x = (playerVelocity.x * deceleration) + (xAcceleration * sensitivity);
    // Limit the maximum velocity of the player sprite, in both directions (positive &amp; negative values)
    if (playerVelocity.x &gt; maxVelocity)
    {
        playerVelocity.x = maxVelocity;
    }
    else if (playerVelocity.x &lt; -maxVelocity)
    {
        playerVelocity.x = -maxVelocity;
    }
}
#pragma mark update
-(void) update:(ccTime)delta
{
    // Gain access to the user input devices / states
    KKInput* input = [KKInput sharedInput];
    [self acceleratePlayerWithX:input.acceleration.smoothedX];
    // Accumulate up the playerVelocity to the player's position
    CGPoint pos = player.position;
    pos.x += playerVelocity.x;
    // The player constrainted to inside the screen
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    // Half the player image size player sprite position is the center of the image
    float imageWidthHalved = [player texture].contentSize.width * 0.5f;
    float leftBorderLimit = imageWidthHalved;
    float rightBorderLimit = screenSize.width - imageWidthHalved;
    // Hit left boundary
    if (pos.x &lt; leftBorderLimit)
    {
        pos.x = leftBorderLimit;
        // Set velocity to zero
        playerVelocity = CGPointZero;
    }
    // Hit right boundary
    else if (pos.x &gt; rightBorderLimit)
    {
        pos.x = rightBorderLimit;
        // Set velocity to zero
        playerVelocity = CGPointZero;
    }
    // Move the player
    player.position = pos; 
    // Collision check
    [self checkForCollision];
}  
#pragma mark MovingTarget

-(void) initMovingTarget
{
    NSLog(@&quot;initMovingTarget&quot;);
    // This is the image
	movingTarget = [CCSprite spriteWithFile:@&quot;red_ball.png&quot;];
    // Add CCSprite for movingTarget
    [self addChild:movingTarget z:0 tag:2];
    // Set the starting position and start movingTarget play sequence
    [self startMovingTargetSequence];
    movingTargetMoveDuration = 4.0f;
   	// Unschedule the selector just in case. If it isn't scheduled it won't do anything.
	[self unschedule:@selector(movingTargetUpdate:)];
	// Schedule the movingTarget update logic to run at the given interval.
	[self schedule:@selector(movingTargetUpdate:) interval:0.1f];
}

-(void) startMovingTargetSequence
{
    NSLog(@&quot;startMovingTargetSequence&quot;);
    // Update score to display increment in totalAttempts
    [self setScore];
    // Increment total attempts to hit a moving target.
    totalAttempts ++;
    // Get the window size
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    // Get the image size
    CGSize imageSize = [movingTarget texture].contentSize;
    // Generate a random x starting position with offsets for center registration point.
    int randomX = CCRANDOM_0_1() * (screenSize.width / imageSize.width);
    movingTarget.position = CGPointMake(imageSize.width * randomX  + imageSize.width * 0.5f, screenSize.height + imageSize.height);
    // Schedule the movingTarget update logic to run at the given interval.
    [self schedule:@selector(movingTargetUpdate:) interval:0.1f];
}

-(void) movingTargetUpdate:(ccTime)delta
{
    // CCSprite-&gt;CCNode no sequence of actions running.
    if ([movingTarget numberOfRunningActions] == 0)
    {
        NSLog(@&quot;movingTargetUpdate&quot;);
        // Determine below screen position.
        CGPoint belowScreenPosition = CGPointMake(movingTarget.position.x, - ( [movingTarget texture].contentSize.height));
        // CCAction to move a CCNode object to the position x,y based on position. 
        CCMoveTo* moveEnd = [CCMoveTo actionWithDuration:movingTargetMoveDuration position:belowScreenPosition];
        // Call back function for the action.
        CCCallFuncN* callEndMovingTargetSequence = [CCCallFuncN actionWithTarget:self selector:@selector(endMovingTargetSequence)];
        // Create a sequence, add the actions: the moveEnd CCMoveTo and the call back function for the end position.
        CCSequence* sequence = [CCSequence actions:moveEnd,callEndMovingTargetSequence, nil];
        // Run the sequence.
        [movingTarget runAction:sequence];
    }
}
-(void) endMovingTargetSequence
{
    NSLog(@&quot;endMovingTargetSequence&quot;);
    [movingTarget stopAllActions];
    // Terminate running the moveTargetUpdate interval.
    [self unschedule:@selector(movingTargetUpdate:)];
    // Decrease the moving target move duration to increase the speed.
    movingTargetMoveDuration -= 0.1f;
    // Moving target move duration is below 2 then hold at 2.
    if (movingTargetMoveDuration &lt; 2.0f)
    {
        movingTargetMoveDuration = 2.0f;
    }
    NSLog(@&quot;movingTargetMoveDuration: %f&quot;,movingTargetMoveDuration);
    // Set the starting position and start movingTarget play sequence
    [self startMovingTargetSequence];
    
}
#pragma mark Collision Check
-(void) checkForCollision
{
	// Size of the player and target. Both are assumed squares so width suffices.
	float playerImageSize = [player texture].contentSize.width;
	float targetImageSize = [movingTarget texture].contentSize.width;
	// Compute their radii. Tweak based on drawing.
	float playerCollisionRadius = playerImageSize *.4;
	float targetCollisionRadius = targetImageSize *.4;
	// This collision distance will roughly equal the image shapes.
	float maxCollisionDistance = playerCollisionRadius + targetCollisionRadius;
    // Distance between two points.
    float actualDistance = ccpDistance(player.position, movingTarget.position);
    
    // Are the two objects closer than allowed?
    if (actualDistance &lt; maxCollisionDistance)
    {
        // Play a sound effect
        [[SimpleAudioEngine sharedEngine] playEffect:@&quot;explosion.caf&quot;];
        totalHits++;
        NSLog(@&quot;HIT! Total attempts: %i. Total hits: %i&quot;, totalHits, totalAttempts);
        [self setScore];
        [self endMovingTargetSequence];
    }
}
#pragma mark score
-(void) initScore
{
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    // Load font information.
    scoreLabel = [CCLabelBMFont labelWithString:@&quot;+0 : 0&quot; fntFile:@&quot;score_glyphs.fnt&quot;];
    scoreLabel.position = CGPointMake(screenSize.width / 2, screenSize.height);
    // Set anchorPoint y position to align with the top of screen.
    scoreLabel.anchorPoint = CGPointMake(0.5f, 1.0f);
}
-(void) setScore
{
    [scoreLabel setString:[NSString stringWithFormat:@&quot;%i : %i : %i&quot;, totalAttempts,totalAttempts-totalHits, totalHits]];
}
@end
</pre>
<p>Two private methods initScore and setScore are declared on lines 17 and 18.</p>
<pre class="brush: objc; highlight: [17,18]; title: ; notranslate">
/*
 * Kobold2D™ --- http://www.kobold2d.org
 *
 * Copyright (c) 2010-2011 Steffen Itterheim. 
 * Released under MIT License in Germany (LICENSE-Kobold2D.txt).
 */

#import &quot;GameLayer.h&quot;
#import &quot;SimpleAudioEngine.h&quot;

@interface GameLayer (PrivateMethods)
-(void) initMovingTarget;
-(void) movingTargetUpdate:(ccTime)delta;
-(void) startMovingTargetSequence;
-(void) endMovingTargetSequence;
-(void) checkForCollision;
-(void) initScore;
-(void) setScore;
@end
</pre>
<p>The CCLabelBMFont could be declared in the init method. I choose a separate method to stop the growth of the init method and also organize related coded into reusable pieces.</p>
<p>That called for getting the screen center again so the score can be centered. </p>
<p>The score_glyphs.fnt file is human readable and contains the information CCLabelBMFont needs to break out the images in score_glyphs.png. Both score_glyphs.fnt and score_glyphs.png where exported from Glyph Designer.  </p>
<p>Line 235 sets up the storing score so the score_glyphs.png is cached.</p>
<p>The anchorPoint property is a convenient way to offset the y position. The Cocos2d documentation recommends not to change the defaults: &#8220;All inner characters are using an anchorPoint of (0.5f, 0.5f) and it is not recommend to change it because it might affect the rendering&#8221;. However it works so we will use it.</p>
<p>Line 242 displays the three score values of totalAttempts, the number of misses and the totalHits.</p>
<pre class="brush: objc; first-line: 230; title: ; notranslate">
#pragma mark score
-(void) initScore
{
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    // Load font information.
    scoreLabel = [CCLabelBMFont labelWithString:@&quot;0 : 0 : 0&quot; fntFile:@&quot;score_glyphs.fnt&quot;];
    scoreLabel.position = CGPointMake(screenSize.width / 2, screenSize.height);
    // Set anchorPoint y position to align with the top of screen.
    scoreLabel.anchorPoint = CGPointMake(0.5f, 1.0f);
}
-(void) setScore
{
    [scoreLabel setString:[NSString stringWithFormat:@&quot;%i : %i : %i&quot;, totalAttempts,totalAttempts-totalHits, totalHits]];
}
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>Step 5 &#8211; GameLayer.m: Initialize the Score in the init Method</strong></p>
<p>On line 66 the score added to the game layer.</p>
<p>On lines 57 and 64 the game information overlay is moved back so the moving target appears over them.</p>
<p>Line 59 updates the subtitle which helps keep track what we are looking at when testing.</p>
<pre class="brush: objc; first-line: 30; highlight: [57,59,64,66]; title: ; notranslate">
-(id) init
{
	if ((self = [super init]))
	{
        // Enable accelerometer input events.
		[KKInput sharedInput].accelerometerActive = YES;
		[KKInput sharedInput].acceleration.filteringFactor = 0.2f;
        // Preload the sound effect into memory so there's no delay when playing it the first time.
		[[SimpleAudioEngine sharedEngine] preloadEffect:@&quot;explosion.caf&quot;];
        // Initialize the total attempts to hit a moving target.
        totalAttempts = 0;
        // Initialize the total hits
        totalHits = 0;
        // Graphic for player
        player = [CCSprite spriteWithFile:@&quot;green_ball.png&quot;];
		[self addChild:player z:0 tag:1];
        // Position player        
        CGSize screenSize = [[CCDirector sharedDirector] winSize];
		float imageHeight = [player texture].contentSize.height;
		player.position = CGPointMake(screenSize.width / 2, imageHeight / 2);
		glClearColor(0.1f, 0.1f, 0.3f, 1.0f);
		// First line of title
		CCLabelTTF* label = [CCLabelTTF labelWithString:@&quot;Kobold2d Intro Tutorial&quot; 
                                               fontName:@&quot;Arial&quot;  
                                               fontSize:30];
		label.position = [CCDirector sharedDirector].screenCenter;
		label.color = ccCYAN;
        [self addChild:label z:-1];
        // Second line of title
 		CCLabelTTF* label2 = [CCLabelTTF labelWithString:@&quot;Lesson 7&quot;
                                                fontName:@&quot;Arial&quot;
                                                fontSize:24];
		label2.color = ccCYAN;
        label2.position = CGPointMake([CCDirector sharedDirector].screenCenter.x ,label.position.y - label.boundingBox.size.height);
        [self addChild:label2 z:-1];
        // The score label initialized
        [self initScore];
        // Add below game action
		[self addChild:scoreLabel z:-1];
        // Seed random number generator
        srandom((UInt32)time(NULL));
        // Initialize our moving target.
        [self initMovingTarget];
        // Start animation -  the update method is called.
        [self scheduleUpdate];;
	}
	return self;
}
</pre>
<p><strong>Step 6 &#8211; GameLayer.m: Update Score For Misses</strong></p>
<p>Line 155 updates the score before incrementing the number of attempts on line 157. If we do it after, the misses would show a value of 1 more than actual each time a new moving target it put into play.</p>
<pre class="brush: objc; first-line: 151; highlight: [155]; title: ; notranslate">
-(void) startMovingTargetSequence
{
    NSLog(@&quot;startMovingTargetSequence&quot;);
    // Update score to display increment in totalAttempts
    [self setScore];
    // Increment total attempts to hit a moving target.
    totalAttempts ++;
    // Get the window size
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    // Get the image size
    CGSize imageSize = [movingTarget texture].contentSize;
    // Generate a random x starting position with offsets for center registration point.
    int randomX = CCRANDOM_0_1() * (screenSize.width / imageSize.width);
    movingTarget.position = CGPointMake(imageSize.width * randomX  + imageSize.width * 0.5f, screenSize.height + imageSize.height);
    // Schedule the movingTarget update logic to run at the given interval.
    [self schedule:@selector(movingTargetUpdate:) interval:0.1f];
}
</pre>
<p><strong>Step 7 &#8211; GameLayer.m: Update Score For Hits</strong></p>
<p>On each hit you want to update the score. The checkForCollision method handles the hits for this game.</p>
<p>You are already displaying score data in the checkForCollision method. So you just need to drop in a call to the setScore method on line 226 just after the class property totalHits is incremented. </p>
<pre class="brush: objc; first-line: 205; highlight: [226]; title: ; notranslate">
#pragma mark Collision Check
-(void) checkForCollision
{
	// Size of the player and target. Both are assumed squares so width suffices.
	float playerImageSize = [player texture].contentSize.width;
	float targetImageSize = [movingTarget texture].contentSize.width;
	// Compute their radii. Tweak based on drawing.
	float playerCollisionRadius = playerImageSize *.4;
	float targetCollisionRadius = targetImageSize *.4;
	// This collision distance will roughly equal the image shapes.
	float maxCollisionDistance = playerCollisionRadius + targetCollisionRadius;
    // Distance between two points.
    float actualDistance = ccpDistance(player.position, movingTarget.position);
    
    // Are the two objects closer than allowed?
    if (actualDistance &lt; maxCollisionDistance)
    {
        // Play a sound effect
        [[SimpleAudioEngine sharedEngine] playEffect:@&quot;explosion.caf&quot;];
        totalHits++;
        NSLog(@&quot;HIT! Total attempts: %i. Total hits: %i&quot;, totalHits, totalAttempts);
        [self setScore];
        [self endMovingTargetSequence];
    }
}
</pre>
<p>That should give you a good starting point for displaying a graphic glyph score.</p>
<p><!-- Place this tag where you want the +1 button to render --><br />
<g:plusone annotation="inline"></g:plusone></p>
<p><a href="http://www.lonhosford.com/lonblog/2011/12/23/kobold2d-xcode-4-introduction-tutorial-lesson-6-add-collision-sound-effect/">&lt;== Lesson 6</a> || <a href="#" onclick = "alert('12/27/11: Lesson 8 - Add Levels\nIN PROGRESS. CHECK BACK LATER');return false">Lesson 8 ==&gt; </a>  </p>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like href="http://www.lonhosford.com/lonblog/2011/12/18/kobold2d-xcode-4-introduction-tutorial-lesson-1-basic-accelerometer/" send="true" width="450" show_faces="true" font=""></fb:like></p>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:comments href="http://www.lonhosford.com/lonblog/2011/12/18/kobold2d-xcode-4-introduction-tutorial-lesson-1-basic-accelerometer/" num_posts="3" width="500"></fb:comments></p>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<!-- Place this render call where appropriate --><br />
<script type="text/javascript">
  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonhosford.com/lonblog/2011/12/27/kobold2d-xcode-4-introduction-tutorial-lesson-7-display-score-using-graphic-glyphs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kobold2D XCode 4 Introduction Tutorial Lesson 6 &#8211; Add Collision Sound Effect</title>
		<link>http://www.lonhosford.com/lonblog/2011/12/23/kobold2d-xcode-4-introduction-tutorial-lesson-6-add-collision-sound-effect/</link>
		<comments>http://www.lonhosford.com/lonblog/2011/12/23/kobold2d-xcode-4-introduction-tutorial-lesson-6-add-collision-sound-effect/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 22:45:04 +0000</pubDate>
		<dc:creator>Lon Hosford</dc:creator>
				<category><![CDATA[Kobold2D]]></category>
		<category><![CDATA[Accelerometer]]></category>
		<category><![CDATA[Cocos2d]]></category>
		<category><![CDATA[CocosDenshion]]></category>
		<category><![CDATA[Gaming]]></category>

		<guid isPermaLink="false">http://www.lonhosford.com/lonblog/?p=2780</guid>
		<description><![CDATA[&#60;== Lesson 5 &#124;&#124; Lesson 7 ==&#62; So far you can see the XCode console window reports the collisions between the player and moving target. Now is time to add some sound. Audio is not integrated into Cocos2D and so a library is required. Fortunately CocosDenshion is an audio library with IOS gaming in mind [...]]]></description>
				<content:encoded><![CDATA[<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like href="http://www.lonhosford.com/lonblog/2011/12/18/kobold2d-xcode-4-introduction-tutorial-lesson-1-basic-accelerometer/" send="true" width="450" show_faces="true" font=""></fb:like><!-- Place this tag where you want the +1 button to render --><br />
<g:plusone annotation="inline"></g:plusone></p>
<p><a href="http://www.lonhosford.com/lonblog/2011/12/22/kobold2d-xcode-4-introduction-tutorial-lesson-5-add-collision-detection/">&lt;== Lesson 5</a> || <a href="http://www.lonhosford.com/lonblog/2011/12/27/kobold2d-xcode-4-introduction-tutorial-lesson-7-display-score-using-graphic-glyphs/" >Lesson 7 ==&gt; </a>  </p>
<p>So far you can see the XCode console window reports the collisions between the player and moving target. <img class="alignleft" src="http://www.lonhosford.com/images/kobold2d/common/blog_article.png" alt="" width="160" height="218" /><br />
<div class="wp-caption alignright" style="width: 131px"><a href="http://www.amazon.com/gp/product/1430238135/ref=as_li_ss_tl?ie=UTF8&#038;tag=hosfordusa&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1430238135" target="_blank"><img  src="https://images-na.ssl-images-amazon.com/images/I/415NHKs30yL._SL160_.jpg" alt="Learn cocos2D Game Development" width="121" height="160" class="  " title="Learn cocos2D Game Development"/></a><p class="wp-caption-text">Learn cocos2D Game Development</p></div> </p>
<p>Now is time to add some sound. Audio is not integrated into Cocos2D and so a library is required.  Fortunately <a href="http://cocos2d-iphone.org/wiki/doku.php/cocosdenshion:faq" target = "_blank">CocosDenshion</a> is an audio library with IOS gaming in mind and is a part of Kobold2D. CocosDenshion is referred to as SimpleAudioEngine in the code.</p>
<p>The file format for playing background sound with CocosDenshion is mp3. For short sound effects, the format recommendation is 16 bit mono wave files for uncompressed audio and IMA4 for lossy compressed audio. You can read more on formats and sound quality choices at <a href="http://cocos2d-iphone.org/wiki/doku.php/cocosdenshion:faq" target = "_blank">CocosDenshion</a> .</p>
<div class="wp-caption aligncenter" style="width: 560px"><img class=" " style="border: 0pt none;" src="http://www.lonhosford.com/images/kobold2d/lesson_06/ipad_running.png" alt="" width="550" height="423" /><p class="wp-caption-text">Finished Lesson Running on IPad2 Simulator</p></div>
<p><strong>Lesson Downloads</strong></p>
<ol>
<li>
<a onclick="javascript: pageTracker._trackPageview('/downloads/kobold2d/intro_tutorial/lesson06/introduction_tutorial_lesson06_assets.zip'); " href="http://www.lonhosford.com/content/kobold2d/intro_tutorial/lesson06/introduction_tutorial_lesson06_assets.zip">Game piece images and sound for project</a></li>
<li>
<a onclick="javascript: pageTracker._trackPageview('/downloads/kobold2d/intro_tutorial/lesson06/introduction_tutorial_common.zip'); " href="http://www.lonhosford.com/content/kobold2d/intro_tutorial/lesson06/introduction_tutorial_common.zip">IPhone images for project</a>. Icons and splash screen.</li>
<li>
<a onclick="javascript: pageTracker._trackPageview('/downloads/kobold2d/intro_tutorial/lesson06/Intro_Tutorial_Lesson_06.zip'); " href="http://www.lonhosford.com/content/kobold2d/intro_tutorial/lesson06/Intro_Tutorial_Lesson_06.zip">Completed Project</a>. This is built in Kobold2d 1.0.1.</li>
</ol>
<p><strong>Step 1 &#8211; Build an Empty-Project Template</strong></p>
<p>You can continue with the <a href="http://www.lonhosford.com/lonblog/2011/12/22/kobold2d-xcode-4-introduction-tutorial-lesson-5-add-collision-detection/">Lesson 5</a> project and make changes noted here. Otherwise the steps for creating this project from an Empty-Project template are the same as <a href="http://www.lonhosford.com/lonblog/2011/12/18/kobold2d-xcode-4-introduction-tutorial-lesson-1-basic-accelerometer/">Lesson 1</a> except to substitute Lesson 6 for Lesson 1 in the project name and to include the red_ball.png, red_ball-hd.png and explosion.caf files when you add the game pieces. The explosion.caf goes in same group as the images. Then you can use the code presented here.</p>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></p>
<p><strong>Step 2 &#8211; Set Properties in config.lua</strong></p>
<p>There are no new configuration properties from Lesson 5. Complete config.lua file is included here for your copy convenience.</p>
<pre class="brush: jscript; collapse: true; light: false; title: ; toolbar: true; notranslate">
--[[
* Kobold2D™ --- http://www.kobold2d.org
*
* Copyright (c) 2010-2011 Steffen Itterheim. 
* Released under MIT License in Germany (LICENSE-Kobold2D.txt).
--]]


--[[
* Need help with the KKStartupConfig settings?
* ------ http://www.kobold2d.com/x/ygMO ------
--]]


local config =
{
    KKStartupConfig = 
    {
        -- load first scene from a class with this name, or from a Lua script with this name with .lua appended
        FirstSceneClassName = &quot;GameLayer&quot;,

        -- set the director type, and the fallback in case the first isn't available
        DirectorType = DirectorType.DisplayLink,
        DirectorTypeFallback = DirectorType.NSTimer,

        MaxFrameRate = 60,
        DisplayFPS = YES,

        EnableUserInteraction = YES,
        EnableMultiTouch = NO,

        -- Render settings
        DefaultTexturePixelFormat = TexturePixelFormat.RGBA8888,
        GLViewColorFormat = GLViewColorFormat.RGB565,
        GLViewDepthFormat = GLViewDepthFormat.DepthNone,
        GLViewMultiSampling = NO,
        GLViewNumberOfSamples = 0,

        Enable2DProjection = NO,
        EnableRetinaDisplaySupport = YES,
        EnableGLViewNodeHitTesting = NO,
        EnableStatusBar = NO,

        -- Orientation &amp; Autorotation
        DeviceOrientation = DeviceOrientation.LandscapeLeft,
        AutorotationType = Autorotation.None,
        ShouldAutorotateToLandscapeOrientations = NO,
        ShouldAutorotateToPortraitOrientations = NO,
        AllowAutorotateOnFirstAndSecondGenerationDevices = NO,

        -- Ad setup
        EnableAdBanner = NO,
        PlaceBannerOnBottom = YES,
        LoadOnlyPortraitBanners = NO,
        LoadOnlyLandscapeBanners = NO,
        AdProviders = &quot;iAd, AdMob&quot;,	-- comma seperated list -&gt; &quot;iAd, AdMob&quot; means: use iAd if available, otherwise AdMob
        AdMobRefreshRate = 15,
        AdMobFirstAdDelay = 5,
        AdMobPublisherID = &quot;YOUR_ADMOB_PUBLISHER_ID&quot;, -- how to get an AdMob Publisher ID: http://developer.admob.com/wiki/PublisherSetup
        AdMobTestMode = YES,

        -- Mac OS specific settings
        AutoScale = NO,
        AcceptsMouseMovedEvents = NO,
        WindowFrame = RectMake(1024-640, 768-480, 640, 480),
        EnableFullScreen = NO,
    },
}

return config
</pre>
<p><strong>Step 3 &#8211; GameLayer.h </strong></p>
<p>There are no changes from Lesson 5 so the entire code is here for your copy and paste convenience.</p>
<pre class="brush: objc; collapse: true; light: false; title: ; toolbar: true; notranslate">
/*
 * Kobold2D™ --- http://www.kobold2d.org
 *
 * Copyright (c) 2010-2011 Steffen Itterheim. 
 * Released under MIT License in Germany (LICENSE-Kobold2D.txt).
 */

#import &quot;kobold2d.h&quot;

@interface GameLayer : CCLayer
{
    CCSprite* player;
    CGPoint playerVelocity;
    CCSprite* movingTarget;
	float movingTargetMoveDuration;
    int totalAttempts;
    int totalHits;
}
@end
</pre>
<p><strong>Step 4 &#8211; Include the SimpleAudioEngine Library</strong></p>
<p>Complete GameLayer.m file is included here for your copy convenience. I will focus on the code changes to accommodate the collision sounds.</p>
<pre class="brush: objc; collapse: true; light: false; title: ; toolbar: true; notranslate">
/*
 * Kobold2D™ --- http://www.kobold2d.org
 *
 * Copyright (c) 2010-2011 Steffen Itterheim. 
 * Released under MIT License in Germany (LICENSE-Kobold2D.txt).
 */

#import &quot;GameLayer.h&quot;
#import &quot;SimpleAudioEngine.h&quot;

@interface GameLayer (PrivateMethods)
-(void) initMovingTarget;
-(void) movingTargetUpdate:(ccTime)delta;
-(void) startMovingTargetSequence;
-(void) endMovingTargetSequence;
-(void) checkForCollision;
@end

// Velocity deceleration
const float deceleration = 0.4f;
// Accelerometer sensitivity (higher = more sensitive)
const float sensitivity = 6.0f;
// Maximum velocity
const float maxVelocity = 100.0f;

@implementation GameLayer

-(id) init
{
	if ((self = [super init]))
	{
        // Enable accelerometer input events.
		[KKInput sharedInput].accelerometerActive = YES;
		[KKInput sharedInput].acceleration.filteringFactor = 0.2f;
        // Preload the sound effect into memory so there's no delay when playing it the first time.
		[[SimpleAudioEngine sharedEngine] preloadEffect:@&quot;explosion.caf&quot;];
        
        // Initialize the total attempts to hit a moving target.
        totalAttempts = 0;
        // Initialize the total hits
        totalHits = 0;
        // Graphic for player
        player = [CCSprite spriteWithFile:@&quot;green_ball.png&quot;];
		[self addChild:player z:0 tag:1];
        // Position player        
        CGSize screenSize = [[CCDirector sharedDirector] winSize];
		float imageHeight = [player texture].contentSize.height;
		player.position = CGPointMake(screenSize.width / 2, imageHeight / 2);
		glClearColor(0.1f, 0.1f, 0.3f, 1.0f);
		// First line of title
		CCLabelTTF* label = [CCLabelTTF labelWithString:@&quot;Kobold2d Intro Tutorial&quot; 
                                               fontName:@&quot;Arial&quot;  
                                               fontSize:30];
		label.position = [CCDirector sharedDirector].screenCenter;
		label.color = ccCYAN;
        [self addChild:label];
        // Second line of title
 		CCLabelTTF* label2 = [CCLabelTTF labelWithString:@&quot;Lesson 6&quot;
                                                fontName:@&quot;Arial&quot;
                                                fontSize:24];
		label2.color = ccCYAN;
        label2.position = CGPointMake([CCDirector sharedDirector].screenCenter.x ,label.position.y - label.boundingBox.size.height);
        [self addChild:label2];
        // Seed random number generator
        srandom((UInt32)time(NULL));
        // Initialize our moving target.
        [self initMovingTarget];
        // Start animation -  the update method is called.
        [self scheduleUpdate];;
	}
	return self;
}
-(void) dealloc
{
#ifndef KK_ARC_ENABLED
	[super dealloc];
#endif // KK_ARC_ENABLED
}
#pragma mark Player Movement
-(void) acceleratePlayerWithX:(double)xAcceleration
{
    // Adjust velocity based on current accelerometer acceleration
    playerVelocity.x = (playerVelocity.x * deceleration) + (xAcceleration * sensitivity);
    // Limit the maximum velocity of the player sprite, in both directions (positive &amp; negative values)
    if (playerVelocity.x &gt; maxVelocity)
    {
        playerVelocity.x = maxVelocity;
    }
    else if (playerVelocity.x &lt; -maxVelocity)
    {
        playerVelocity.x = -maxVelocity;
    }
}
#pragma mark update
-(void) update:(ccTime)delta
{
    // Gain access to the user input devices / states
    KKInput* input = [KKInput sharedInput];
    [self acceleratePlayerWithX:input.acceleration.smoothedX];
    // Accumulate up the playerVelocity to the player's position
    CGPoint pos = player.position;
    pos.x += playerVelocity.x;
    // The player constrainted to inside the screen
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    // Half the player image size player sprite position is the center of the image
    float imageWidthHalved = [player texture].contentSize.width * 0.5f;
    float leftBorderLimit = imageWidthHalved;
    float rightBorderLimit = screenSize.width - imageWidthHalved;
    // Hit left boundary
    if (pos.x &lt; leftBorderLimit)
    {
        pos.x = leftBorderLimit;
        // Set velocity to zero
        playerVelocity = CGPointZero;
    }
    // Hit right boundary
    else if (pos.x &gt; rightBorderLimit)
    {
        pos.x = rightBorderLimit;
        // Set velocity to zero
        playerVelocity = CGPointZero;
    }
    // Move the player
    player.position = pos; 
    // Collision check
    [self checkForCollision];
}  
#pragma mark MovingTarget

-(void) initMovingTarget
{
    NSLog(@&quot;initMovingTarget&quot;);
    // This is the image
	movingTarget = [CCSprite spriteWithFile:@&quot;red_ball.png&quot;];
    // Add CCSprite for movingTarget
    [self addChild:movingTarget z:0 tag:2];
    // Set the starting position and start movingTarget play sequence
    [self startMovingTargetSequence];
    movingTargetMoveDuration = 4.0f;
   	// Unschedule the selector just in case. If it isn't scheduled it won't do anything.
	[self unschedule:@selector(movingTargetUpdate:)];
	// Schedule the movingTarget update logic to run at the given interval.
	[self schedule:@selector(movingTargetUpdate:) interval:0.1f];
}

-(void) startMovingTargetSequence
{
    NSLog(@&quot;startMovingTargetSequence&quot;);
    // Increment total attempts to hit a moving target.
    totalAttempts ++;
    // Get the window size
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    // Get the image size
    CGSize imageSize = [movingTarget texture].contentSize;
    // Generate a random x starting position with offsets for center registration point.
    int randomX = CCRANDOM_0_1() * (screenSize.width / imageSize.width);
    movingTarget.position = CGPointMake(imageSize.width * randomX  + imageSize.width * 0.5f, screenSize.height + imageSize.height);
    // Schedule the movingTarget update logic to run at the given interval.
    [self schedule:@selector(movingTargetUpdate:) interval:0.1f];
}

-(void) movingTargetUpdate:(ccTime)delta
{
    // CCSprite-&gt;CCNode no sequence of actions running.
    if ([movingTarget numberOfRunningActions] == 0)
    {
        NSLog(@&quot;movingTargetUpdate&quot;);
        // Determine below screen position.
        CGPoint belowScreenPosition = CGPointMake(movingTarget.position.x, - ( [movingTarget texture].contentSize.height));
        // CCAction to move a CCNode object to the position x,y based on position. 
        CCMoveTo* moveEnd = [CCMoveTo actionWithDuration:movingTargetMoveDuration position:belowScreenPosition];
        // Call back function for the action.
        CCCallFuncN* callEndMovingTargetSequence = [CCCallFuncN actionWithTarget:self selector:@selector(endMovingTargetSequence)];
        // Create a sequence, add the actions: the moveEnd CCMoveTo and the call back function for the end position.
        CCSequence* sequence = [CCSequence actions:moveEnd,callEndMovingTargetSequence, nil];
        // Run the sequence.
        [movingTarget runAction:sequence];
    }
}
-(void) endMovingTargetSequence
{
    NSLog(@&quot;endMovingTargetSequence&quot;);
    [movingTarget stopAllActions];
    // Terminate running the moveTargetUpdate interval.
    [self unschedule:@selector(movingTargetUpdate:)];
    // Decrease the moving target move duration to increase the speed.
    movingTargetMoveDuration -= 0.1f;
    // Moving target move duration is below 2 then hold at 2.
    if (movingTargetMoveDuration &lt; 2.0f)
    {
        movingTargetMoveDuration = 2.0f;
    }
    NSLog(@&quot;movingTargetMoveDuration: %f&quot;,movingTargetMoveDuration);
    // Set the starting position and start movingTarget play sequence
    [self startMovingTargetSequence];
}
#pragma mark Collision Check
-(void) checkForCollision
{
	// Size of the player and target. Both are assumed squares so width suffices.
	float playerImageSize = [player texture].contentSize.width;
	float targetImageSize = [movingTarget texture].contentSize.width;
	// Compute their radii. Tweak based on drawing.
	float playerCollisionRadius = playerImageSize *.4;
	float targetCollisionRadius = targetImageSize *.4;
	// This collision distance will roughly equal the image shapes.
	float maxCollisionDistance = playerCollisionRadius + targetCollisionRadius;
    // Distance between two points.
    float actualDistance = ccpDistance(player.position, movingTarget.position);
    
    // Are the two objects closer than allowed?
    if (actualDistance &lt; maxCollisionDistance)
    {
        // Play a sound effect
        [[SimpleAudioEngine sharedEngine] playEffect:@&quot;explosion.caf&quot;];
        totalHits++;
        NSLog(@&quot;HIT! Total attempts: %i. Total hits: %i&quot;, totalAttempts, totalHits);
        [self endMovingTargetSequence];
    }
}
@end

</pre>
<p>First the sound effect library is needed. Line 9 accomplishes that for you.</p>
<pre class="brush: objc; highlight: [9]; title: ; notranslate">
/*
 * Kobold2D™ --- http://www.kobold2d.org
 *
 * Copyright (c) 2010-2011 Steffen Itterheim. 
 * Released under MIT License in Germany (LICENSE-Kobold2D.txt).
 */

#import &quot;GameLayer.h&quot;
#import &quot;SimpleAudioEngine.h&quot;

@interface GameLayer (PrivateMethods)
-(void) initMovingTarget;
-(void) movingTargetUpdate:(ccTime)delta;
-(void) startMovingTargetSequence;
-(void) endMovingTargetSequence;
-(void) checkForCollision;
@end

</pre>
<p><strong>Step 5 &#8211; Preload the Collision Sound Effect</strong></p>
<p>Next you can preload the sound effect file to avoid a delay the first time it is played. The init method is the perfect place to do the preloading and line 36 shows how it is done with SimpleAudioEngine.</p>
<pre class="brush: objc; first-line: 28; highlight: [36]; title: ; notranslate">
-(id) init
{
	if ((self = [super init]))
	{
        // Enable accelerometer input events.
		[KKInput sharedInput].accelerometerActive = YES;
		[KKInput sharedInput].acceleration.filteringFactor = 0.2f;
        // Preload the sound effect into memory so there's no delay when playing it the first time.
		[[SimpleAudioEngine sharedEngine] preloadEffect:@&quot;explosion.caf&quot;];
        
        // Initialize the total attempts to hit a moving target.
        totalAttempts = 0;
        // Initialize the total hits
        totalHits = 0;
        // Graphic for player
        player = [CCSprite spriteWithFile:@&quot;green_ball.png&quot;];
		[self addChild:player z:0 tag:1];
        // Position player        
        CGSize screenSize = [[CCDirector sharedDirector] winSize];
		float imageHeight = [player texture].contentSize.height;
		player.position = CGPointMake(screenSize.width / 2, imageHeight / 2);
		glClearColor(0.1f, 0.1f, 0.3f, 1.0f);
		// First line of title
		CCLabelTTF* label = [CCLabelTTF labelWithString:@&quot;Kobold2d Intro Tutorial&quot; 
                                               fontName:@&quot;Arial&quot;  
                                               fontSize:30];
		label.position = [CCDirector sharedDirector].screenCenter;
		label.color = ccCYAN;
        [self addChild:label];
        // Second line of title
 		CCLabelTTF* label2 = [CCLabelTTF labelWithString:@&quot;Lesson 6&quot;
                                                fontName:@&quot;Arial&quot;
                                                fontSize:24];
		label2.color = ccCYAN;
        label2.position = CGPointMake([CCDirector sharedDirector].screenCenter.x ,label.position.y - label.boundingBox.size.height);
        [self addChild:label2];
        // Seed random number generator
        srandom((UInt32)time(NULL));
        // Initialize our moving target.
        [self initMovingTarget];
        // Start animation -  the update method is called.
        [self scheduleUpdate];;
	}
	return self;
}
</pre>
<p><strong>Step 6 &#8211; Play the Collision Sound Effect</strong></p>
<p>Playing the sound effect is done in the checkForCollision method and is a single line of code on line 215.</p>
<pre class="brush: objc; first-line: 197; highlight: [215]; title: ; notranslate">
#pragma mark Collision Check
-(void) checkForCollision
{
	// Size of the player and target. Both are assumed squares so width suffices.
	float playerImageSize = [player texture].contentSize.width;
	float targetImageSize = [movingTarget texture].contentSize.width;
	// Compute their radii. Tweak based on drawing.
	float playerCollisionRadius = playerImageSize *.4;
	float targetCollisionRadius = targetImageSize *.4;
	// This collision distance will roughly equal the image shapes.
	float maxCollisionDistance = playerCollisionRadius + targetCollisionRadius;
    // Distance between two points.
    float actualDistance = ccpDistance(player.position, movingTarget.position);
    
    // Are the two objects closer than allowed?
    if (actualDistance &lt; maxCollisionDistance)
    {
        // Play a sound effect
        [[SimpleAudioEngine sharedEngine] playEffect:@&quot;explosion.caf&quot;];
        totalHits++;
        NSLog(@&quot;HIT! Total attempts: %i. Total hits: %i&quot;, totalAttempts, totalHits);
        [self endMovingTargetSequence];
    }
}
</pre>
<p>You should be all set to hear crashes as you tilt your IPad or IPhone and try to intercept our falling target.</p>
<p><!-- Place this tag where you want the +1 button to render --><br />
<g:plusone annotation="inline"></g:plusone></p>
<p><a href="http://www.lonhosford.com/lonblog/2011/12/22/kobold2d-xcode-4-introduction-tutorial-lesson-5-add-collision-detection/">&lt;== Lesson 5</a> || <a href="http://www.lonhosford.com/lonblog/2011/12/27/kobold2d-xcode-4-introduction-tutorial-lesson-7-display-score-using-graphic-glyphs/" >Lesson 7 ==&gt; </a>  </p>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like href="http://www.lonhosford.com/lonblog/2011/12/18/kobold2d-xcode-4-introduction-tutorial-lesson-1-basic-accelerometer/" send="true" width="450" show_faces="true" font=""></fb:like></p>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:comments href="http://www.lonhosford.com/lonblog/2011/12/18/kobold2d-xcode-4-introduction-tutorial-lesson-1-basic-accelerometer/" num_posts="3" width="500"></fb:comments></p>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<!-- Place this render call where appropriate --><br />
<script type="text/javascript">
  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonhosford.com/lonblog/2011/12/23/kobold2d-xcode-4-introduction-tutorial-lesson-6-add-collision-sound-effect/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
