<?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>iPhoneGeek 爱疯极客 &#187; 游戏</title>
	<atom:link href="http://www.iphone-geek.cn/tag/%e6%b8%b8%e6%88%8f/feed" rel="self" type="application/rss+xml" />
	<link>http://www.iphone-geek.cn</link>
	<description>iPhone 新闻，编程，技巧与提示，代码，教程</description>
	<lastBuildDate>Sun, 25 Jul 2010 13:49:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>跨平台游戏引擎开发实录之一 &#8211; 设计文档</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e8%b7%a8%e5%b9%b3%e5%8f%b0%e6%b8%b8%e6%88%8f%e5%bc%95%e6%93%8e%e5%bc%80%e5%8f%91%e5%ae%9e%e5%bd%95%e4%b9%8b%e4%b8%80-%e8%ae%be%e8%ae%a1%e6%96%87%e6%a1%a3</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e8%b7%a8%e5%b9%b3%e5%8f%b0%e6%b8%b8%e6%88%8f%e5%bc%95%e6%93%8e%e5%bc%80%e5%8f%91%e5%ae%9e%e5%bd%95%e4%b9%8b%e4%b8%80-%e8%ae%be%e8%ae%a1%e6%96%87%e6%a1%a3#comments</comments>
		<pubDate>Mon, 18 Jan 2010 06:03:09 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[游戏]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[开源项目]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=797</guid>
		<description><![CDATA[我目前正在开发一个跨平台游戏引擎，我准备将整个开发过程通过博客记录下来。欢迎各位朋友提出宝贵意见。

下面是我的设计文档初稿。

项目名称
 
Portable Game Engine （PGE ）

目标

跨平台，希望能支持Windows，Linux，Mac OSX，iPhone，WinCE, Android, Blackberry, Symbian phone 等
简单，尽量简化编程接口
2D和3D
组件可选，以减小目标代码
支持Unicode


组件

核心：游戏主循环，线程，垃圾收集，插件等
图形系统（采用OpenGL或OpenGL ES）：图像（纹理），动画，字体
声音系统（采用OpenAL）：音效，音乐，乐器
资源管理器：压缩/解压，加密/解密
输入：键盘，鼠标及触摸屏（重力感应）
网络：Tcp/ip，Http, UDP
GUI（用户接口）：菜单，文本，按钮，列表框，下拉框，选择框
游戏AI
游戏Physics


开发按阶段进行。第一阶段开发Windows下的OpenGL 2D引擎，然后移植到iPhone下。
]]></description>
			<content:encoded><![CDATA[<p>我目前正在开发一个跨平台游戏引擎，我准备将整个开发过程通过博客记录下来。欢迎各位朋友提出宝贵意见。</p>
<p><br class="spacer_" /></p>
<p>下面是我的设计文档初稿。</p>
<p><br class="spacer_" /></p>
<h3>项目名称</h3>
<p><strong> </strong></p>
<p><strong>Portable Game Engine （PGE ）</strong></p>
<p><br class="spacer_" /></p>
<h3>目标</h3>
<ul>
<li>跨平台，希望能支持Windows，Linux，Mac OSX，iPhone，WinCE, Android, Blackberry, Symbian phone 等</li>
<li>简单，尽量简化编程接口</li>
<li>2D和3D</li>
<li>组件可选，以减小目标代码</li>
<li>支持Unicode</li>
</ul>
<p><br class="spacer_" /></p>
<h3>组件</h3>
<ul>
<li>核心：游戏主循环，线程，垃圾收集，插件等</li>
<li>图形系统（采用OpenGL或OpenGL ES）：图像（纹理），动画，字体</li>
<li>声音系统（采用OpenAL）：音效，音乐，乐器</li>
<li>资源管理器：压缩/解压，加密/解密</li>
<li>输入：键盘，鼠标及触摸屏（重力感应）</li>
<li>网络：Tcp/ip，Http, UDP</li>
<li>GUI（用户接口）：菜单，文本，按钮，列表框，下拉框，选择框</li>
<li>游戏AI</li>
<li>游戏Physics</li>
</ul>
<p><br class="spacer_" /></p>
<p>开发按阶段进行。第一阶段开发Windows下的OpenGL 2D引擎，然后移植到iPhone下。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e8%b7%a8%e5%b9%b3%e5%8f%b0%e6%b8%b8%e6%88%8f%e5%bc%95%e6%93%8e%e5%bc%80%e5%8f%91%e5%ae%9e%e5%bd%95%e4%b9%8b%e4%b8%80-%e8%ae%be%e8%ae%a1%e6%96%87%e6%a1%a3/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flash游戏，iPhone用户准备好了吗？</title>
		<link>http://www.iphone-geek.cn/%e6%96%b0%e9%97%bb/flash%e6%b8%b8%e6%88%8f%ef%bc%8ciphone%e7%94%a8%e6%88%b7%e5%87%86%e5%a4%87%e5%a5%bd%e4%ba%86%e5%90%97%ef%bc%9f</link>
		<comments>http://www.iphone-geek.cn/%e6%96%b0%e9%97%bb/flash%e6%b8%b8%e6%88%8f%ef%bc%8ciphone%e7%94%a8%e6%88%b7%e5%87%86%e5%a4%87%e5%a5%bd%e4%ba%86%e5%90%97%ef%bc%9f#comments</comments>
		<pubDate>Mon, 21 Dec 2009 03:33:18 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[新闻]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=468</guid>
		<description><![CDATA[（译者批：本人并不看好此公司。因为Adobe即将推出最新beta版的flash cs5。谁愿意分一杯羹给别人呢？特别是这杯羹是如此之大 &#8211; 50%的净收入）
&#160;
iPhone引领的休闲游戏复兴的风潮似乎已经过热。感谢早些时候Adobe发布的新Flash开发软件beta版，一个新启动的公司OneAppAtATime允许开发者使用Flash开发iPhone程序。从本周开始，此公司为Flash游戏开发者打开了一道大门，他们提供将Flash游戏转换为iPhone游戏并使其获得App Store批准的服务，作为回报他们将收取35%的收入。（也就是说在Apple拿走30%后与开发者平分剩下的70%。）
&#160;
OneAppAtATime 是Evan “Rabble” Henshaw-Plath的杰作，他们以前曾为源于Yahoo Brickhouse的卫星服务公司Fire Eagle以及传播Twitter的播客公司Odeo工作。
&#160;
Henshaw-Plath，位于乌拉圭的蒙得维的亚，宣称希望每月生产“数十甚至数百个游戏“。他们的目标是许多Flash游戏的兼职开发者以及由于网上用户不希望付费过去有困难从他们的项目中赚到钱的开发者。
&#160;
但是在iPhone平台上，人们通常是需要付费的，Henshaw-Plath希望将这些游戏的价格定在$2.99。而且尽管Adobe宣布 计划在2009年底发布Flash专业CS5的公众beta版，OneAppAtATime在竞争中已经抢先一步。Henshaw-Plath宣称他通过乌拉圭大量的Flash开发者获得了先机。
&#160;
不像它的名称，OneAppAtATime希望成为一个工厂，能够大量生产出尽可能多的程序，但是，Henshaw-Plath特别希望能够改编利用了iPhone特性如重力计，GPS，罗盘和地址簿的程序。例如，一个公司的游戏利用Atari经典的Breakout游戏允许玩家通过前后移动设备来控制他们的摇杆。（由于这些程序还没有通过Apple的批准，你现在还不能玩这个游戏。）

&#160;
Henshaw-Plath通过其Ruby on Rails顾问公司Cubox注资。他希望通常需要“数百甚至数千美金”开发的每个Flash游戏只需花几天时间转换。
&#160;
OneAppAtATime正在释放一个怪物；目前已经有大约100,000 iPhone程序，而且有远超此数的Flash游戏存在。具有如此之多的竞争，维持生意并不是件容易的事情。Henshaw-Plath说他的程序将在与其他iPhone程序的竞争中胜出因为用户在购买之前可以通过Flash进行测试。而且他还并不具有对游戏的独家许可证，这样Flash开发者在认为他们可以做得更好时有权与OneAppAtATime竞争。并且公司保证为每个游戏提供大量的公共市场宣传和广告。
&#160;
原文见：iPhone Users, Get Ready for Flash Games
]]></description>
			<content:encoded><![CDATA[<p>（译者批：本人并不看好此公司。因为Adobe即将推出最新beta版的flash cs5。谁愿意分一杯羹给别人呢？特别是这杯羹是如此之大 &#8211; 50%的净收入）</p>
<p>&nbsp;</p>
<p>iPhone引领的休闲游戏复兴的风潮似乎已经过热。感谢早些时候Adobe发布的新Flash开发软件beta版，一个新启动的公司<a href="http://oneappatatime.com/">OneAppAtATime</a>允许开发者使用Flash开发iPhone程序。从本周开始，此公司为Flash游戏开发者打开了一道大门，他们提供将Flash游戏转换为iPhone游戏并使其获得App Store批准的服务，作为回报他们将收取35%的收入。（也就是说在Apple拿走30%后与开发者平分剩下的70%。）</p>
<p>&nbsp;</p>
<p>OneAppAtATime 是<a href="http://anarchogeek.com/">Evan “Rabble” Henshaw-Plath</a>的杰作，他们以前曾为源于Yahoo Brickhouse的卫星服务公司Fire Eagle以及传播Twitter的播客公司Odeo工作。</p>
<p>&nbsp;</p>
<p>Henshaw-Plath，位于乌拉圭的蒙得维的亚，宣称希望每月生产“数十甚至数百个游戏“。他们的目标是许多Flash游戏的兼职开发者以及由于网上用户不希望付费过去有困难从他们的项目中赚到钱的开发者。</p>
<p>&nbsp;</p>
<p>但是在iPhone平台上，人们通常是需要付费的，Henshaw-Plath希望将这些游戏的价格定在$2.99。而且尽管Adobe<a href="http://labs.adobe.com/technologies/flashcs5/appsfor_iphone/">宣布</a> 计划在2009年底发布Flash专业CS5的公众beta版，OneAppAtATime在竞争中已经抢先一步。Henshaw-Plath宣称他通过乌拉圭大量的Flash开发者获得了先机。</p>
<p>&nbsp;</p>
<p>不像它的名称，OneAppAtATime希望成为一个工厂，能够大量生产出尽可能多的程序，但是，Henshaw-Plath特别希望能够改编利用了iPhone特性如重力计，GPS，罗盘和地址簿的程序。例如，一个公司的游戏利用Atari经典的Breakout游戏允许玩家通过前后移动设备来控制他们的摇杆。（由于这些程序还没有通过Apple的批准，你现在还不能玩这个游戏。）</p>
<p><a rel="attachment wp-att-86326" href="http://www.iphone-geek.cn/?attachment_id=86326"><img title="Picture 8" src="http://gigaom.files.wordpress.com/2009/12/picture-8.png?w=349&amp;h=233" alt="" width="349" height="233" /></a></p>
<p>&nbsp;</p>
<p>Henshaw-Plath通过其Ruby on Rails顾问公司<a href="http://cuboxsa.com/">Cubox</a>注资。他希望通常需要“数百甚至数千美金”开发的每个Flash游戏只需花几天时间转换。</p>
<p>&nbsp;</p>
<p>OneAppAtATime正在释放一个怪物；目前已经有大约<a href="http://gigaom.com/2009/11/04/100000-apps/">100,000</a> iPhone程序，而且有远超此数的Flash游戏存在。具有如此之多的竞争，维持生意并不是件容易的事情。Henshaw-Plath说他的程序将在与其他iPhone程序的竞争中胜出因为用户在购买之前可以通过Flash进行测试。而且他还并不具有对游戏的独家许可证，这样Flash开发者在认为他们可以做得更好时有权与OneAppAtATime竞争。并且公司保证为每个游戏提供大量的公共市场宣传和广告。</p>
<p>&nbsp;</p>
<h5>原文见：<a href="http://gigaom.com/2009/12/15/iphone-users-get-ready-for-flash-games/">iPhone Users, Get Ready for Flash Games</a></h5>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e6%96%b0%e9%97%bb/flash%e6%b8%b8%e6%88%8f%ef%bc%8ciphone%e7%94%a8%e6%88%b7%e5%87%86%e5%a4%87%e5%a5%bd%e4%ba%86%e5%90%97%ef%bc%9f/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenGL ES 02 &#8211; 绘制基本图形2 &#8211; 正方形</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/opengl-es-02-%e7%bb%98%e5%88%b6%e5%9f%ba%e6%9c%ac%e5%9b%be%e5%bd%a22-%e6%ad%a3%e6%96%b9%e5%bd%a2</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/opengl-es-02-%e7%bb%98%e5%88%b6%e5%9f%ba%e6%9c%ac%e5%9b%be%e5%bd%a22-%e6%ad%a3%e6%96%b9%e5%bd%a2#comments</comments>
		<pubDate>Sun, 15 Nov 2009 10:11:43 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[图形图像]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[OpenGL ES]]></category>
		<category><![CDATA[教程]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=238</guid>
		<description><![CDATA[严格地说，正方形不是OpenGL ES的基元，但是它们确实是很基本的，而且渲染正方形像渲染三角形一样容易。本教程中，我们将把绘制三角形基元的代码转变成正方形的代码。我们仍将采用静态渲染，但我们会很简单地介绍一下变换（如移动）。当然，一旦我们绘制了正方形，我们就可以绘制正方体，然后甚至是带纹理映射的正方体&#8230;&#8230;
&#160;

简单概括一下本教程

&#160;
上一次教程，我们在一个“空白画布”Xcode项目上渲染了一个实体三角形。然后建立一个顶点数组，通过使用glVertexPointer()告诉OpenGL数据及其格式，再使用glDrawArrays()渲染出来。

&#160;
今天，我们将使用上次的代码，但把三角形变为正方形。我们仅需要改动其中几行代码。第一部分应该很明显，我们应为正方形指定4点而不是三角形的3点。然后我们通过传递给glDrawArrays()不同的参数告诉OpenGL以不同的方式绘画。

&#160;
我们开始吧。

&#160;
定义正方形顶点

&#160;
打开上次教程的Xcode项目并找到rawView 方法。为riangleVertices[] 常量加上注释-先不要删除，因为当我们讨论变换时会需要用到它们-加入下列代码：

12345678const GLfloat squareVertices&#91;&#93; = &#123;

        -1.0, 1.0, -6.0,            // Top left
        -1.0, -1.0, -6.0,           // Bottom left
        1.0, -1.0, -6.0,            // Bottom right
        1.0, 1.0, -6.0              // Top right

    &#125;;

&#160;
这定义了我们的正方形。注意反时针方向的正方形顶点（4个点）。

&#160;
然后我们在主体部分为绘制三角形代码加上注释，稍后我们也会用回这些代码的。为三个函数glVertexArray(), glEnableClientState()和glDrawArrays()加上注释并加入下列代码：

&#160;
12345    glVertexPointer&#40;3, GL_FLOAT, 0, squareVertices&#41;;

    glEnableClientState&#40;GL_VERTEX_ARRAY&#41;;

    glDrawArrays&#40;GL_TRIANGLE_FAN, 0, 4&#41;;

&#160;
这三个函数只有少许不同。

&#160;
1glVertexPointer&#40;3, GL_FLOAT, 0, squareVertices&#41;;

&#160;
这里唯一的变化是使用了不同的顶点数组，即正方形数组而不是三角形数组。

&#160;

glEnableClientState()仍然是通知OpenGL从顶点数组绘制（而不是绘制颜色数组或其它）。

&#160;
1glDrawArrays&#40;GL_TRIANGLE_FAN, 0, 4&#41;;

&#160;
最主要的变化就在这里了。上次的教程我们使用GL_TRIANGLES作为第一个参数，3为第三个参数。记住第二个参数代表数组开始位置的偏移量，因为我们的顶点数组只包括了正方形，所以它还是0。

&#160;
第一参数是OpenGL的绘图模式，你已经见过其中两种。就此机会我讨论一下各种不同的绘图模式。它们是：

&#160;
GL_POINTS
GL_LINES
GL_LINE_LOOP
GL_LINE_STRIP
GL_TRIANGLES
GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN

&#160;
我们还没有讨论过点和线，所以我们先把重点放在后面三种与三角形有关的模式。在我开始讲解之前，我要提醒你们一个顶点数组可能包括不止一个三角形，所以虽然你只见过一个顶点数组包括一个对象，但并不限如此。

&#160;
GL_TRIANGLES  &#8211; 表示OpenGL将以是三个顶点一组来处理顶点数组。所以，第一组三个顶点代表三角形顶点1，2和3。然后再处理接下来的一组三个顶点，直到数组的尾部。

&#160;
GL_TRIANGLE_STRIP  &#8211; OpenGL将从前两个顶点开始，对于各个后续顶点，它将与前两个顶点一起构成三角形。也就是说，squareVertices[6~8]是与squareVerticies[0~2]和squareVerticies[3~5]一起构成三角形的。而squareVertices[9~11]是与squareVertices[3~5]和squareVertices[6~8]构成三角形的。如此这般，完成整个数组。

&#160;
注意：squareVertices[0~2]表示：

        squareVertices[0]  &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>严格地说，正方形不是OpenGL ES的基元，但是它们确实是很基本的，而且渲染正方形像渲染三角形一样容易。本教程中，我们将把绘制三角形基元的代码转变成正方形的代码。我们仍将采用静态渲染，但我们会很简单地介绍一下变换（如移动）。当然，一旦我们绘制了正方形，我们就可以绘制正方体，然后甚至是带纹理映射的正方体&#8230;&#8230;</p>
<p>&nbsp;</p>
<p><span id="more-238"></span></p>
<h2>简单概括一下本教程<br />
</h2>
<p>&nbsp;</p>
<p>上一次教程，我们在一个“空白画布”Xcode项目上渲染了一个实体三角形。然后建立一个顶点数组，通过使用glVertexPointer()告诉OpenGL数据及其格式，再使用glDrawArrays()渲染出来。
</p>
<p>&nbsp;</p>
<p>今天，我们将使用上次的代码，但把三角形变为正方形。我们仅需要改动其中几行代码。第一部分应该很明显，我们应为正方形指定4点而不是三角形的3点。然后我们通过传递给glDrawArrays()不同的参数告诉OpenGL以不同的方式绘画。
</p>
<p>&nbsp;</p>
<p>我们开始吧。
</p>
<p>&nbsp;</p>
<h2>定义正方形顶点<br />
</h2>
<p>&nbsp;</p>
<p>打开上次教程的Xcode项目并找到rawView 方法。为riangleVertices[] 常量加上注释-先不要删除，因为当我们讨论变换时会需要用到它们-加入下列代码：
</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #a61390;">const</span> GLfloat squareVertices<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">&#123;</span><br />
<br />
        <span style="color: #002200;">-</span><span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">6.0</span>,            <span style="color: #11740a; font-style: italic;">// Top left</span><br />
        <span style="color: #002200;">-</span><span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">6.0</span>,           <span style="color: #11740a; font-style: italic;">// Bottom left</span><br />
        <span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">6.0</span>,            <span style="color: #11740a; font-style: italic;">// Bottom right</span><br />
        <span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">6.0</span>              <span style="color: #11740a; font-style: italic;">// Top right</span><br />
<br />
    <span style="color: #002200;">&#125;</span>;</div></td></tr></tbody></table></div>
</p>
<p>&nbsp;</p>
<p>这定义了我们的正方形。注意反时针方向的正方形顶点（4个点）。
</p>
<p>&nbsp;</p>
<p>然后我们在主体部分为绘制三角形代码加上注释，稍后我们也会用回这些代码的。为三个函数glVertexArray(), glEnableClientState()和glDrawArrays()加上注释并加入下列代码：
</p>
<p>&nbsp;</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">    glVertexPointer<span style="color: #002200;">&#40;</span>3, GL_FLOAT, 0, squareVertices<span style="color: #002200;">&#41;</span>;<br />
<br />
    glEnableClientState<span style="color: #002200;">&#40;</span>GL_VERTEX_ARRAY<span style="color: #002200;">&#41;</span>;<br />
<br />
    glDrawArrays<span style="color: #002200;">&#40;</span>GL_TRIANGLE_FAN, 0, 4<span style="color: #002200;">&#41;</span>;</div></td></tr></tbody></table></div>
</p>
<p>&nbsp;</p>
<p>这三个函数只有少许不同。
</p>
<p>&nbsp;</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">glVertexPointer<span style="color: #002200;">&#40;</span>3, GL_FLOAT, 0, squareVertices<span style="color: #002200;">&#41;</span>;</div></td></tr></tbody></table></div>
</p>
<p>&nbsp;</p>
<p>这里唯一的变化是使用了不同的顶点数组，即正方形数组而不是三角形数组。
</p>
<p>&nbsp;</p>
<p>
glEnableClientState()仍然是通知OpenGL从顶点数组绘制（而不是绘制颜色数组或其它）。
</p>
<p>&nbsp;</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">glDrawArrays<span style="color: #002200;">&#40;</span>GL_TRIANGLE_FAN, 0, 4<span style="color: #002200;">&#41;</span>;</div></td></tr></tbody></table></div>
</p>
<p>&nbsp;</p>
<p>最主要的变化就在这里了。上次的教程我们使用GL_TRIANGLES作为第一个参数，3为第三个参数。记住第二个参数代表数组开始位置的偏移量，因为我们的顶点数组只包括了正方形，所以它还是0。
</p>
<p>&nbsp;</p>
<p>第一参数是OpenGL的绘图模式，你已经见过其中两种。就此机会我讨论一下各种不同的绘图模式。它们是：
</p>
<p>&nbsp;</p>
<p>GL_POINTS<br />
GL_LINES<br />
GL_LINE_LOOP<br />
GL_LINE_STRIP<br />
GL_TRIANGLES<br />
GL_TRIANGLE_STRIP<br />
GL_TRIANGLE_FAN
</p>
<p>&nbsp;</p>
<p>我们还没有讨论过点和线，所以我们先把重点放在后面三种与三角形有关的模式。在我开始讲解之前，我要提醒你们一个顶点数组可能包括不止一个三角形，所以虽然你只见过一个顶点数组包括一个对象，但并不限如此。
</p>
<p>&nbsp;</p>
<p>GL_TRIANGLES  &#8211; 表示OpenGL将以是三个顶点一组来处理顶点数组。所以，第一组三个顶点代表三角形顶点1，2和3。然后再处理接下来的一组三个顶点，直到数组的尾部。
</p>
<p>&nbsp;</p>
<p>GL_TRIANGLE_STRIP  &#8211; OpenGL将从前两个顶点开始，对于各个后续顶点，它将与前两个顶点一起构成三角形。也就是说，squareVertices[6~8]是与squareVerticies[0~2]和squareVerticies[3~5]一起构成三角形的。而squareVertices[9~11]是与squareVertices[3~5]和squareVertices[6~8]构成三角形的。如此这般，完成整个数组。
</p>
<p>&nbsp;</p>
<p>注意：squareVertices[0~2]表示：
</p>
<p>        squareVertices[0]  &#8211; X 坐标
</p>
<p>        squareVertices[1] &#8211; Y 坐标
</p>
<p>        squareVertices[2] &#8211; Z 坐标
</p>
<p>&nbsp;</p>
<p>如果你还不明白，我将在随后的示例中进一步说明。
</p>
<p>&nbsp;</p>
<p>GL_TRIANGLE_FAN  &#8211; 对于最前面两个顶点之后的每个后续顶点，OpenGL将使用前一个顶点以及第一个顶点构成三角形。所以，对于squareVertices[6~8]，它是通过与squareVertices[3~5] （前一个顶点）和squareVertices[0~2] （第一个顶点）一起构成三角形的。
</p>
<p>&nbsp;</p>
<p>我们使用的是GL_TRIANGLES_FAN。按下“Build &amp; Go”后，你可以在屏幕上看到如下白色正方形：
</p>
<p>
</p>
<div>
<div>
<div><img src="http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/3/28_OpenGL_ES_02_-_Drawing_Primitives_2_-_Squares_files/square.png" alt=""></div>
</p></div>
<p>
</div>
<p>回头看看顶点数组。想象一下三角形是这样被绘制从而构成正方形的。OpenGL是这样进行渲染的。
</p>
<p>&nbsp;</p>
<p>三角形顶点1: squareVertices[0~2]        &#8212; 正方形的左上角
</p>
<p>三角形顶点2: squareVertices[3~5]        &#8212; 正方形的左下角
</p>
<p>三角形顶点3: squareVertices[6~8]        &#8212; 正方形的右下角
</p>
<p>&nbsp;</p>
<p>OpenGL使用上叙三点绘制的三角形组成了正方形的左下部分。设想下按对角线从左上角开始到右下角将正方形分成两部分。注意两个三角形是怎样构成的？OpenGL只是画了正方形左下方一半。
</p>
<p>&nbsp;</p>
<p>注意：squareVertices[0~2]表示：
</p>
<p>        squareVertices[0] - X坐标
</p>
<p>        squareVertices[1] &#8211; Y坐标
</p>
<p>        squareVertices[2] &#8211; Z坐标
</p>
<p>&nbsp;</p>
<p>三角形顶点1: squareVertices[9~11]       &#8211; 正方形右上方顶点
</p>
<p>三角形顶点2: squareVertices[6~8]        &#8212; 前一个顶点，右下顶点
</p>
<p>三角形顶点3: squareVertices[0~2]        &#8212; 第一顶点，左上顶点
</p>
<p>&nbsp;</p>
<p>只要使用一个新点，OpenGL就能渲染三角形以完成整个正方形的渲染。
</p>
<p>&nbsp;</p>
<p>GL_TRIANGLE_STRIP
</p>
<p>回到代码将glDrawArrays()第一个参数从GL_TRIANGLE_FAN改为GL_TRIANGLE_STRIP：
</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">        glDrawArrays<span style="color: #002200;">&#40;</span>GL_TRIANGLE_STRIP, 0, 4<span style="color: #002200;">&#41;</span>;</div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>按 “Build &amp; Go” ，你将看到下列图形：
</p>
<p>
</p>
<div>
<div>
<div><img src="http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/3/28_OpenGL_ES_02_-_Drawing_Primitives_2_-_Squares_files/trianglesstrip.jpg" alt=""></div>
</p></div>
<p>
</div>
<p>&nbsp;</p>
<p>让我们分析下为什么在绘制方法中的一个变化就会导致我们得不到正方形的结果。OpenGL以以下方法处理顶点数组：
</p>
<p>&nbsp;</p>
<p>三角形顶点 1: squareVertices[0~2]        &#8212; 左上
</p>
<p>三角形顶点 2: squareVertices[3~5]        &#8212; 左下
</p>
<p>三角形顶点 3: squareVertices[6~8]        &#8212; 右下
</p>
<p>&nbsp;</p>
<p>OpenGL现在是使用最前面的三点渲染三角形，因此，正方形左下半部分三角形的渲染已前面例子的结果一样。
</p>
<p>&nbsp;</p>
<p>三角形顶点 1: squareVertices[9~11]       &#8211; 右上
</p>
<p>三角形顶点 2: squareVertices[6~8]        &#8212; 前一个顶点，右下
</p>
<p>三角形顶点 3: squareVertices[3~5]        &#8212; 再前一个顶点，左下
</p>
<p>&nbsp;</p>
<p>OpenGL现在是使用这三点来渲染三角形。在本例中，使渲染的三角形与构成正方形所需的三角形相比，正好翻转了90度。
</p>
<p>&nbsp;</p>
<p>如果我们用不同方式提供顶点数组，我们有可能像使用GL_TRIANGLE_STRIP获得正确正方形，就像使用GL_TRIANGLE_FAN一样。需要记住绘制方法必须与顶点数组一起考虑，否则有可能得到奇怪的结果，就像我们将FAN改为STRIP时一样。
</p>
<p>&nbsp;</p>
<p>注意：如果你以不同方式设定顶点数组，使用GL_TRIANGLE_STRIP你仍可以画出正确的正方形。例如：
</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">    <span style="color: #a61390;">const</span> GLfloat stripSquare<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">&#123;</span><br />
<br />
        <span style="color: #002200;">-</span><span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">6.0</span>,               <span style="color: #11740a; font-style: italic;">// 左下</span><br />
        <span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">6.0</span>,                <span style="color: #11740a; font-style: italic;">// 右下</span><br />
        <span style="color: #002200;">-</span><span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">6.0</span>,                <span style="color: #11740a; font-style: italic;">// 左上</span><br />
        <span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span>, <span style="color: #002200;">-</span><span style="color: #2400d9;">6.0</span>                  <span style="color: #11740a; font-style: italic;">// 右上</span><br />
    <span style="color: #002200;">&#125;</span>;</div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>使用上述三点，可以看到第一个三角形是通过前三个顶点构成的，获得的三角形如下：
</p>
<p>&nbsp;</p>
<div>
<div>
<div><img src="http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/3/28_OpenGL_ES_02_-_Drawing_Primitives_2_-_Squares_files/gltrianglestrip1.png" alt=""></div>
</p></div>
<p>
</div>
<p>&nbsp;</p>
<p>现在，通过指定右上顶点（P4），与左上（P3）和右下的再前一个顶点（P2）可以构成一个新三角形。新顶点用橘红，绿色和红色表示如下：
</p>
<p>
</p>
<div>
<div>
<div><img src="http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/3/28_OpenGL_ES_02_-_Drawing_Primitives_2_-_Squares_files/gltrianglestrip2.png" alt=""></div>
</p></div>
<p>
</div>
<p>&nbsp;</p>
<p>我们正确地绘制了一个正方形。最终的结果是一样的，但需要提醒你的是，指定的顶点数组必须与绘图方法匹配。
</p>
<p>&nbsp;</p>
<h2>结论<br />
</h2>
<p>&nbsp;</p>
<p>我们已经讨论了三角形和正方形。还剩下点和线部分。这两种基元都十分简单，将在下一篇教程中涉及。对于本次教程已经涉及的部分，下次我们将进行混色处理。
</p>
<p>&nbsp;</p>
<p>在完成了物体着色后，我们将移动和进行3D纹理映射。当然，它不会是Doom 3式的程序，不过我们可以由此开始建立3D物体。然后，我们就将进入3D世界了。
</p>
<p>&nbsp;</p>
<p>本教程的源代码：<a href="http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/3/28_OpenGL_ES_02_-_Drawing_Primitives_2_-_Squares_files/AppleCoder-OpenGLES-02.zip" title="28_OpenGL_ES_02_-_Drawing_Primitives_2_-_Squares_files/AppleCoder-OpenGLES-02.zip">AppleCoder-OpenGLES-02.zip</a>
</p>
<p>&nbsp;</p>
<h5>原文见：<a href="http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/3/28_OpenGL_ES_02_-_Drawing_Primitives_2_-_Squares.html">OpenGL ES 02 &#8211; Drawing Primitives 2 &#8211; Squares</a>&nbsp;作者：Simon Maurice &nbsp;上一篇：<a href="编程/opengl-es-01-绘制基本图形1-三角形">opengl-es-01-绘制基本图形1-三角形</a></h5>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/opengl-es-02-%e7%bb%98%e5%88%b6%e5%9f%ba%e6%9c%ac%e5%9b%be%e5%bd%a22-%e6%ad%a3%e6%96%b9%e5%bd%a2/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone游戏编程教程之四-游戏简单音频</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e5%9b%9b-%e6%b8%b8%e6%88%8f%e7%ae%80%e5%8d%95%e9%9f%b3%e9%a2%91</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e5%9b%9b-%e6%b8%b8%e6%88%8f%e7%ae%80%e5%8d%95%e9%9f%b3%e9%a2%91#comments</comments>
		<pubDate>Fri, 13 Nov 2009 10:42:33 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[游戏]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[音频]]></category>
		<category><![CDATA[教程]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=235</guid>
		<description><![CDATA[本教程系列的最后一讲将介绍怎样为你的游戏加上声音。由于这是针对初学者的教程，所以我不会讨论复杂的音频技术，如OpenGL和Audio Queue。今天的主题是播放一段短的声音（少于30秒）。如果你不要求任何背景音乐，这将是最容易的播放音频的方式了。这种方式的缺点是一次只能播放一个音频文件。好，我们开始吧&#8230;&#8230;先从上次教程的代码开始。我们今天将使用两种声音，一个是击打球的声音，另一个是得分的声音。

&#160;

下面是你需要下载的音频文件：

clapping-crowd-studio-01
tennis-volley-01

&#160;
注意文件的格式是.caf。你所有音频文件格式必须符合在iPhone上播放的要求。Apple提供了一个工具将音频转换成这种格式。这里是参考。很简单，打开终端输入：
&#160;
/usr/bin/afconvert -f caff -d LEI16 {INPUT} {OUTPUT}
&#160;
 {INPUT}是输入音频文件路径，{OUTPUT} 是你想要存放的.caf文件路径。
&#160;
将音频文件添加到项目中
&#160;
将下载好的音频文件拖放到项目下的Resources文件夹。如果你还希望 安排得更为有序些的话，你还可以建立一个Audio子文件夹。请确定在“copy the  files into your project’s directory”检查框上打勾。

&#160;
添加AudioToolbox.framework到项目
&#160;
由于我们要用到此框架的一些函数，所以我们必须将此框架加入项目中。右击项目中的Frameworks文件夹选择Add -&#62; Existing Frameworks。在搜索框内输入AudioToolbox.framework 然后选择搜索结果中的框架。（请确定点取了Computer 以搜索整个电脑）。

&#160;
找到所需框架后，按Add。现在我们已经准备好写代码了&#8230;&#8230;
&#160;
头文件声明
&#160;
打开 iTennisViewController.h 加入下列代码：

&#160;
首先我们看到代码引入AudioServices.h，我们需要使用其中一些函数来播放音频。接下来定义了两个SystemSoundID。它们都是Integers（整数型，也可以使用int，但会引起许多警告信息）。然后打开iTennishViewController.m加入下面代码：

&#160;
现在我们来初始化声音对象。找到viewDidLoad方法加入下列代码：

&#160;
很简单吧。第一行是获取音频文件路径。下一行是将路径转换为CFURLRef。最后，加载音频文件并与指定soundID联系起来。注意我们传递的&#38;clappingFileID参数，  这是通过参考地址传递的，因此它允许AudioServicesCreateSystemSoundID方法对其进行修改。我们用同样方法处理击球声。下面，我们可以开始播放了。
&#160;
声音播放
&#160;
播放加载好的声音实际上很简单。只需将需要播放文件的soundID传递给AudioServicesPlaySystemSound方法即可。所以播放得分时的鼓掌声只需在reset方法中加入下列代码：

&#160;
请注意，我们传递的clappingFileID说明我们是要播放鼓掌声。加在gameLoop中加入下列代码将播放球拍击球的声音：

&#160;
很容易吧？按“Build and Go”试玩我们的游戏吧。源代码下载 。
&#160;
原文见：iPhone Game Programming Tutorial Part 4 – Basic Game Audio  
]]></description>
			<content:encoded><![CDATA[<p>本教程系列的最后一讲将介绍怎样为你的游戏加上声音。由于这是针对初学者的教程，所以我不会讨论复杂的音频技术，如OpenGL和Audio Queue。今天的主题是播放一段短的声音（少于30秒）。如果你不要求任何背景音乐，这将是最容易的播放音频的方式了。这种方式的缺点是一次只能播放一个音频文件。好，我们开始吧&#8230;&#8230;先从上次教程的代码开始。我们今天将使用两种声音，一个是击打球的声音，另一个是得分的声音。
</p>
<p>&nbsp;</p>
<p><span id="more-235"></span></p>
<p>下面是你需要下载的音频文件：</p>
<ul>
<li><a href="http://icodeblog.com/wp-content/uploads/2009/05/clapping-crowd-studio-01.caf">clapping-crowd-studio-01</a></li>
<li><a href="http://icodeblog.com/wp-content/uploads/2009/05/tennis-volley-01.caf">tennis-volley-01</a></li>
</ul>
<p>&nbsp;</p>
<p>注意文件的格式是.caf。你所有音频文件格式必须符合在iPhone上播放的要求。Apple提供了一个工具将音频转换成这种格式。这里是<a href="CONVERT_AN_AUDIO_FILE_TO_THE_PREFERRED_FORMAT_FOR_IPHONE_OS">参考</a>。很简单，打开终端输入：</p>
<p>&nbsp;</p>
<p><strong>/usr/bin/afconvert -f caff -d LEI16 {INPUT} {OUTPUT}</strong></p>
<p>&nbsp;</p>
<p> {INPUT}是输入音频文件路径，{OUTPUT} 是你想要存放的.caf文件路径。</p>
<p>&nbsp;</p>
<h2>将音频文件添加到项目中</h2>
<p>&nbsp;</p>
<p>将下载好的音频文件拖放到项目下的Resources文件夹。如果你还希望 安排得更为有序些的话，你还可以建立一个Audio子文件夹。请确定在“copy the  files into your project’s directory”检查框上打勾。</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_01.png"><img title="screenshot_01" src="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_01.png" alt="screenshot_01" width="232" height="240"></a></p>
<p>&nbsp;</p>
<h2>添加AudioToolbox.framework到项目</h2>
<p>&nbsp;</p>
<p>由于我们要用到此框架的一些函数，所以我们必须将此框架加入项目中。右击项目中的<strong>Frameworks</strong>文件夹选择<strong>Add -&gt; Existing Frameworks</strong>。在搜索框内输入<strong>AudioToolbox.framework </strong>然后选择搜索结果中的框架。（请确定点取了<strong>Computer</strong> 以搜索整个电脑）。</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_02.png"><img title="screenshot_02" src="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_02.png" alt="screenshot_02" width="532" height="427"></a></p>
<p>&nbsp;</p>
<p>找到所需框架后，按<strong>Add</strong>。现在我们已经准备好写代码了&#8230;&#8230;</p>
<p>&nbsp;</p>
<h2>头文件声明</h2>
<p>&nbsp;</p>
<p>打开 <strong>iTennisViewController.h</strong> 加入下列代码：</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_11.png"><img title="screenshot_11" src="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_11.png" alt="screenshot_11" width="325" height="356"></a></p>
<p>&nbsp;</p>
<p>首先我们看到代码引入AudioServices.h，我们需要使用其中一些函数来播放音频。接下来定义了两个SystemSoundID。它们都是Integers（整数型，也可以使用int，但会引起许多警告信息）。然后打开<strong>iTennishViewController.m</strong>加入下面代码：</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_09.png"><img title="screenshot_09" src="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_09.png" alt="screenshot_09" width="258" height="27"></a></p>
<p>&nbsp;</p>
<p>现在我们来初始化声音对象。找到viewDidLoad方法加入下列代码：</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_12.png"><img title="screenshot_12" src="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_12.png" alt="screenshot_12" width="709" height="223"></a></p>
<p>&nbsp;</p>
<p>很简单吧。第一行是获取音频文件路径。下一行是将路径转换为CFURLRef。最后，加载音频文件并与指定soundID联系起来。注意我们传递的&amp;clappingFileID参数，  这是通过参考地址传递的，因此它允许AudioServicesCreateSystemSoundID方法对其进行修改。我们用同样方法处理击球声。下面，我们可以开始播放了。</p>
<p>&nbsp;</p>
<h2>声音播放</h2>
<p>&nbsp;</p>
<p>播放加载好的声音实际上很简单。只需将需要播放文件的soundID传递给AudioServicesPlaySystemSound方法即可。所以播放得分时的鼓掌声只需在reset方法中加入下列代码：</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_14.png"><img title="screenshot_14" src="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_14.png" alt="screenshot_14" width="322" height="52"></a></p>
<p>&nbsp;</p>
<p>请注意，我们传递的clappingFileID说明我们是要播放鼓掌声。加在gameLoop中加入下列代码将播放球拍击球的声音：</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_15.png"><img title="screenshot_15" src="http://icodeblog.com/wp-content/uploads/2009/05/screenshot_15.png" alt="screenshot_15" width="381" height="209"></a></p>
<p>&nbsp;</p>
<p>很容易吧？按“Build and Go”试玩我们的游戏吧。源代码<a href="http://icodeblog.com/wp-content/uploads/2009/05/itennis-4.zip">下载</a> 。</p>
<p>&nbsp;</p>
<h5>原文见：<a href="http://icodeblog.com/2009/05/04/iphone-game-programming-tutorial-part-4-basic-game-audio/" rel="bookmark" title="Permanent Link to iPhone Game Programming Tutorial Part 4 – Basic Game Audio">iPhone Game Programming Tutorial Part 4 – Basic Game Audio </a> </h5>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e5%9b%9b-%e6%b8%b8%e6%88%8f%e7%ae%80%e5%8d%95%e9%9f%b3%e9%a2%91/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>一款App Store上架游戏的源代码</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e4%b8%80%e6%ac%beapp-store%e4%b8%8a%e6%9e%b6%e6%b8%b8%e6%88%8f%e7%9a%84%e6%ba%90%e4%bb%a3%e7%a0%81</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e4%b8%80%e6%ac%beapp-store%e4%b8%8a%e6%9e%b6%e6%b8%b8%e6%88%8f%e7%9a%84%e6%ba%90%e4%bb%a3%e7%a0%81#comments</comments>
		<pubDate>Fri, 13 Nov 2009 02:43:35 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[开源项目]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[源代码]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=223</guid>
		<description><![CDATA[发现一款App Store上架游戏的源代码，游戏名为Tweejump。它是以Cocos2D为引擎的。想学习开源Cocos2D引擎的朋友可以参考下。

源码下载地址在Github，直接按“Download&#8221;就可以下载了。
]]></description>
			<content:encoded><![CDATA[<p>发现一款App Store上架游戏的源代码，游戏名为<a href="http://iplayful.com/tweejump/">Tweejump</a>。它是以Cocos2D为引擎的。想学习开源Cocos2D引擎的朋友可以参考下。</p>
<p><img alt="" src="http://iplayful.com/tweejump/tweejump.jpg" title="tweejump" class="alignnone" width="318" height="459" /></p>
<p>源码下载地址在<a href="http://github.com/haqu/tweejump">Github</a>，直接按“Download&#8221;就可以下载了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e4%b8%80%e6%ac%beapp-store%e4%b8%8a%e6%9e%b6%e6%b8%b8%e6%88%8f%e7%9a%84%e6%ba%90%e4%bb%a3%e7%a0%81/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenGL ES系列之0 &#8211; 建立Xcode项目</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone-opengl-es%e7%b3%bb%e5%88%97%e4%b9%8b0-%e5%bb%ba%e7%ab%8bxcode%e9%a1%b9%e7%9b%ae</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone-opengl-es%e7%b3%bb%e5%88%97%e4%b9%8b0-%e5%bb%ba%e7%ab%8bxcode%e9%a1%b9%e7%9b%ae#comments</comments>
		<pubDate>Wed, 11 Nov 2009 10:53:03 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[图形图像]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[OpenGL ES]]></category>
		<category><![CDATA[教程]]></category>

		<guid isPermaLink="false">http://www.iphone-geek.cn/?p=182</guid>
		<description><![CDATA[
为iPhone建立一个OpenGL ES的Xcode项目是很容易的事，特别是在苹果公司的SDK发布时引入了模板的概念后。我们所需要做的只是在适当的地方快速而简单的加入代码。这就是我们今天的主题。

&#160;
老实说，如果你只是想早点切入OpenGL 教程的主题，你尽可以忽略这一部分。而且这样做，你也不会错失什么，因为有关Xcode设定部分我并不准备过多涉猎。尽管进入教程的最后部分下载项目文件。
&#160;
启动Xcode并创建Xcode新项目。选择模板&#8220;OpenGL ES Application&#8221;（见图1），然后将项目存储在你认为方便的地方。&#160;
&#160;



&#160;&#160;
图1
&#160;
好，我们假定你肯能以前已经在哪看过这个模板或运行过用这个模板建立的项目。我们说要做的就是移除那个旋转的彩色正方形的有关代码并将其转换成使用深度缓冲的视图（即使其成为&#8220;真正的&#8221;3D）。
&#160;
3D空间的2D
  
&#160;
像Apple的模板一样，大部分OpenGL教程开始都忽略深度，通常都使用2维坐标系统（X,Y)而不是更复杂的3维坐标系统（X,Y,Z)。你可能已经注意到Apple模板中的正方形定点使用（X,Y)，这是因为他们没有使用深度。
&#160;
这叫做正交投影。本教程系列的目标是带你进入3D世界。所以我现在不会讨论正交投影；可能稍后的系列会有提及。现在我们直接向3D世界进发吧。
  
&#160;
允许Depth Buffer（深度缓存）
  
&#160;
我们要作的第一件事是允许深度缓存。Apple示例中的正方形只是一个2D物体，所以根本不需要深度缓存。由于我们需要深度，所以我们必须启用它。Apple已经提供了设定深度缓存的代码，我们正好可以使用。
  
&#160;
在编辑器中打开EAGLView.m找到下面代码:
  
1#define USE_DEPTH_BUFFER 0

不用多说，把0改为1。这将启用视图设定部分创建深度缓存的代码。代码在createFrameBuffer方法中。现在还不需要考虑太多这段代码。它是Apple写的，应该能正常工作。
  
&#160;
现在我们需要启用深度来测试OpenGL。我们要建立一个新方法，它只会被调用一次以使视图正常工作。首先，建立一个新方法setupView并将下面代码加入新方法中：  
1234567891011121314151617- &#40;void&#41;setupView &#123;
&#160; &#160; const GLfloat zNear = 0.1, zFar = 1000.0, fieldOfView = 60.0;
&#160; &#160; GLfloat size;
&#160; &#160; glEnable&#40;GL_DEPTH_TEST&#41;;

&#160; &#160; glMatrixMode&#40;GL_PROJECTION&#41;;

&#160; &#160; size = zNear * tanf&#40;DEGREES_TO_RADIANS&#40;fieldOfView&#41; / 2.0&#41;;

&#160; &#160; // This give [...]]]></description>
			<content:encoded><![CDATA[<div>
<p>为iPhone建立一个OpenGL ES的Xcode项目是很容易的事，特别是在苹果公司的SDK发布时引入了模板的概念后。我们所需要做的只是在适当的地方快速而简单的加入代码。这就是我们今天的主题。</p>
<p><span id="more-182"></span></p>
<p>&nbsp;</p>
<p>老实说，如果你只是想早点切入OpenGL 教程的主题，你尽可以忽略这一部分。而且这样做，你也不会错失什么，因为有关Xcode设定部分我并不准备过多涉猎。尽管进入教程的最后部分下载项目文件。</p>
<p>&nbsp;</p>
<p>启动Xcode并创建Xcode新项目。选择模板&ldquo;OpenGL ES Application&rdquo;（见图1），然后将项目存储在你认为方便的地方。&nbsp;</p>
<p>&nbsp;</p>
<div>
<div><img alt="" src="http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/3/28_OpenGL_ES_00_-_Xcode_Project_Set_Up_files/figure01.png"></div>
</p></div>
<p>&nbsp;&nbsp;</p>
<h5>图1</h5>
<p>&nbsp;</p>
<p>好，我们假定你肯能以前已经在哪看过这个模板或运行过用这个模板建立的项目。我们说要做的就是移除那个旋转的彩色正方形的有关代码并将其转换成使用深度缓冲的视图（即使其成为&ldquo;真正的&rdquo;3D）。</p>
<p>&nbsp;</p>
<h2>3D空间的2D<br />
  </h2>
<p>&nbsp;</p>
<p>像Apple的模板一样，大部分OpenGL教程开始都忽略深度，通常都使用2维坐标系统（X,Y)而不是更复杂的3维坐标系统（X,Y,Z)。你可能已经注意到Apple模板中的正方形定点使用（X,Y)，这是因为他们没有使用深度。</p>
<p>&nbsp;</p>
<p>这叫做正交投影。本教程系列的目标是带你进入3D世界。所以我现在不会讨论正交投影；可能稍后的系列会有提及。现在我们直接向3D世界进发吧。
  </p>
<p>&nbsp;</p>
<p>允许Depth Buffer（深度缓存）
  </p>
<p>&nbsp;</p>
<p>我们要作的第一件事是允许深度缓存。Apple示例中的正方形只是一个2D物体，所以根本不需要深度缓存。由于我们需要深度，所以我们必须启用它。Apple已经提供了设定深度缓存的代码，我们正好可以使用。
  </p>
<p>&nbsp;</p>
<p>在编辑器中打开EAGLView.m找到下面代码:
  </p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #6e371a;">#define USE_DEPTH_BUFFER 0</span></div></td></tr></tbody></table></div>
</p>
<p>不用多说，把0改为1。这将启用视图设定部分创建深度缓存的代码。代码在createFrameBuffer方法中。现在还不需要考虑太多这段代码。它是Apple写的，应该能正常工作。
  </p>
<p>&nbsp;</p>
<p>现在我们需要启用深度来测试OpenGL。我们要建立一个新方法，它只会被调用一次以使视图正常工作。首先，建立一个新方法setupView并将下面代码加入新方法中：  </p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setupView <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">const</span> GLfloat zNear <span style="color: #002200;">=</span> 0.1, zFar <span style="color: #002200;">=</span> 1000.0, fieldOfView <span style="color: #002200;">=</span> <span style="color: #2400d9;">60.0</span>;<br />
&nbsp; &nbsp; GLfloat size;<br />
&nbsp; &nbsp; glEnable<span style="color: #002200;">&#40;</span>GL_DEPTH_TEST<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; glMatrixMode<span style="color: #002200;">&#40;</span>GL_PROJECTION<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; size <span style="color: #002200;">=</span> zNear <span style="color: #002200;">*</span> tanf<span style="color: #002200;">&#40;</span>DEGREES_TO_RADIANS<span style="color: #002200;">&#40;</span>fieldOfView<span style="color: #002200;">&#41;</span> <span style="color: #002200;">/</span> 2.0<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// This give us the size of the iPhone display</span><br />
&nbsp; &nbsp; CGRect rect <span style="color: #002200;">=</span> self.bounds;<br />
<br />
&nbsp; &nbsp; glFrustumf<span style="color: #002200;">&#40;</span><span style="color: #002200;">-</span>size, size, <span style="color: #002200;">-</span>size <span style="color: #002200;">/</span> <span style="color: #002200;">&#40;</span>rect.size.width <span style="color: #002200;">/</span> rect.size.height<span style="color: #002200;">&#41;</span>, size <span style="color: #002200;">/</span> <span style="color: #002200;">&#40;</span>rect.size.width <span style="color: #002200;">/</span> rect.size.height<span style="color: #002200;">&#41;</span>, zNear, zFar<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; glViewport<span style="color: #002200;">&#40;</span>0, 0, rect.size.width, rect.size.height<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; glClearColor<span style="color: #002200;">&#40;</span>0.0f, 0.0f, 0.0f, 1.0f<span style="color: #002200;">&#41;</span>;<br />
<span style="color: #002200;">&#125;</span></div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>上述代码通过建立一个映射到世界显示的视区设定了OpenGL操作的环境。我将稍后详细说明，现在注意下面代码：</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">glEnable<span style="color: #002200;">&#40;</span>GL_DEPTH_TEST<span style="color: #002200;">&#41;</span>;</div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>此代码启用了OpenGL中的深度测试。你需要记住在OpenGL中一旦你启用了什么，你一定要记住在你不需要时要关闭它。由于我们启用深度测试并没有关闭，所以在视图设定中仍然有效。</p>
<p><div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">glClearColor(0.0f, 0.0f, 0.0f, 1.0f);</div></td></tr></tbody></table></div>
</p>
<p>&nbsp;</p>
<p>我们在此定义了清屏时所用的颜色。OpenGLES中所有颜色都必须是RGBA值（即红，绿，蓝和alpha），而不能像OpenGL一样采用RGB值。由于OpenGLES已经知道清屏时采用的颜色，所以清屏时使用定义的黑色。此设定一直保持到我们改变它。</p>
<p>&nbsp;</p>
<p>当使用浮点时，颜色值为0-&gt;1，而使用无符号字节类型时，可为0-&gt;255。数值越大，所代表颜色的密度越高。
  </p>
<p>&nbsp;</p>
<p>好，回到文件最开始我们先前改变的#define处。我们要在这定义一个宏，在我们刚插入的setupView方法中需要用到。</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color: #6e371a;">#define USE_DEPTH_BUFFER 1</span><br />
&nbsp; <br />
&nbsp; <span style="color: #6e371a;">#define DEGREES_TO_RADIANS(__ANGLE) ((__ANGLE) / 180.0 * M_PI)</span></div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<h2>视图绘制 &#8211; 画图方法<br />
  </h2>
<p>&nbsp;</p>
<p>现在，找到drawView方法。这是本教程的重点。Apple已经提示我们这里是视图绘制的地方。</p>
<p>&nbsp;</p>
<p>首先，删除一切，加入下面代码：
  </p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>drawView <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>EAGLContext setCurrentContext<span style="color: #002200;">:</span>context<span style="color: #002200;">&#93;</span>;<span style="color: #002200;">&amp;</span>nbsp;<span style="color: #002200;">&amp;</span>nbsp;<span style="color: #002200;">&amp;</span>nbsp; <br />
&nbsp; &nbsp; glBindFramebufferOES<span style="color: #002200;">&#40;</span>GL_FRAMEBUFFER_OES, viewFramebuffer<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; glViewport<span style="color: #002200;">&#40;</span>0, 0, backingWidth, backingHeight<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; glBindRenderbufferOES<span style="color: #002200;">&#40;</span>GL_RENDERBUFFER_OES, viewRenderbuffer<span style="color: #002200;">&#41;</span>;<br />
&nbsp; <br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>context presentRenderbuffer<span style="color: #002200;">:</span>GL_RENDERBUFFER_OES<span style="color: #002200;">&#93;</span>;<br />
<span style="color: #002200;">&#125;</span></div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>上面代码的前三行是设定作图空间。后两行是将作图空间与当前屏幕可见空间进行交换。如果你以前进行过动画或游戏编程工作，那么你应该知道这叫做 &ldquo;double buffered（双重缓冲）&rdquo;。</p>
<p>&nbsp;</p>
<p>如果不知道，我们解释下：我们创建了两个完全相同的缓冲，一个用于显示给用户，另一个被清理掉然后在其上绘图。在绘制结束后，我们交换这两个视图以便用户看到新的视图。我们之所以不拍麻烦做了这么多事情是为了动画更为平滑。
  </p>
<p>&nbsp;</p>
<p>我们还要加入更多的代码。</p>
<p>&nbsp;</p>
<p>首先，在dealloc方法前插入以下代码：</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>checkGLError<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>visibleCheck <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; GLenum error <span style="color: #002200;">=</span> glGetError<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;<br />
&nbsp; <br />
&nbsp; &nbsp; <span style="color: #a61390;">switch</span> <span style="color: #002200;">&#40;</span>error<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">case</span> GL_INVALID_ENUM<span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;GL Error: Enum argument is out of range&quot;</span><span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">case</span> GL_INVALID_VALUE<span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;GL Error: Numeric value is out of range&quot;</span><span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">break</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">case</span> GL_INVALID_OPERATION<span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;GL Error: Operation illegal in current state&quot;</span><span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">break</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">case</span> GL_STACK_OVERFLOW<span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;GL Error: Command would cause a stack overflow&quot;</span><span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #a61390;">break</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">case</span> GL_STACK_UNDERFLOW<span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;GL Error: Command would cause a stack underflow&quot;</span><span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">break</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">case</span> GL_OUT_OF_MEMORY<span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;GL Error: Not enough memory to execute command&quot;</span><span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">break</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">case</span> GL_NO_ERROR<span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>visibleCheck<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;No GL Error&quot;</span><span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">break</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">default</span><span style="color: #002200;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unknown GL Error&quot;</span><span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">break</span>;<br />
<br />
<span style="color: #002200;">&#125;</span></div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>OpenGL有一套错误检查的方法（glGetError())，但是需要将错误码转换成更容易读的格式。上面的代码就是完成这个工作的。</p>
<p>&nbsp;</p>
<p>布尔值&ldquo;visibleCheck&rdquo;只用于检查当没有错误时此方法是否已被调用。 </p>
<p>&nbsp;</p>
<p>最后，我们要做的只是在EAGLView.m中找到initWithCoder方法并调用&ldquo;setupView&rdquo;方法。在变量&ldquo;animationInterval&rdquo;设定之前，加入下面代码调用setupView：</p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #002200;">&#91;</span>self setupView<span style="color: #002200;">&#93;</span>;</div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>应注意我们只是调用在initWithCoder中setupView方法而不是创建一个新方法，它只应该被调用一次。</p>
<p>下面，打开EAGLView.h！</p>
<p>&nbsp;</p>
<h3>EAGLView.h<br />
  </h3>
<p>&nbsp;</p>
<p>我们只需要在这里加入两个方法的原型：
  </p>
<div class="codecolorer-container objc mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setupView;<br />
<br />
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>checkGLError<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>visibleCheck;</div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>教程到此结束。</p>
<p>&nbsp;</p>
<h2>后续&#8230;<br />
  </h2>
<p>&nbsp;</p>
<p>如果你此时按&ldquo;build and run&rdquo;，那么在simulator（模拟器）上只是显示一个空白屏幕。在下一个教程中，我们将在屏幕上绘制一下基本图形，基本图形是指点，线和三角形之类的元素。</p>
<p>&nbsp;</p>
<p>
  代码下载：<a href="http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/3/28_OpenGL_ES_00_-_Xcode_Project_Set_Up_files/AppleCoder-OpenGLES-00.zip" title="28_OpenGL_ES_00_-_Xcode_Project_Set_Up_files/AppleCoder-OpenGLES-00.zip">AppleCoder-OpenGLES-00.zip</a>
  </p>
<p>&nbsp;</p>
<h5>原文见： <a href="http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/3/28_OpenGL_ES_00_-_Xcode_Project_Set_Up.html">OpenGL ES 00 &#8211; Xcode Project Set Up</a> 作者：Simon Maurice</h5>
<div>
<h5></h5>
</p></div>
</div>
<div> </div>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone-opengl-es%e7%b3%bb%e5%88%97%e4%b9%8b0-%e5%bb%ba%e7%ab%8bxcode%e9%a1%b9%e7%9b%ae/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone游戏编程教程之三- 启动画面</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e4%b8%89-%e5%90%af%e5%8a%a8%e7%94%bb%e9%9d%a2</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e4%b8%89-%e5%90%af%e5%8a%a8%e7%94%bb%e9%9d%a2#comments</comments>
		<pubDate>Wed, 18 Mar 2009 08:02:05 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[游戏]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[教程]]></category>

		<guid isPermaLink="false">http://iphonegeek.zuesitech.com/?p=165</guid>
		<description><![CDATA[今天，我将介绍怎样为你的程序加一些&#8220;铃和哨&#8221;（注：指一些附加的花哨的东西）是你的游戏显得更完整。首先，我们为游戏增加一个启动页面。

&#160;
创建启动页面
&#160;
我们加入的启动页面将淡出到游戏主屏幕。你可以下载此图像加入到项目的Resources（资源）文件夹中。 请选择复选框中&#8220;copy this image to the project&#8217;s directory（拷贝此 图像至项目目录）&#8221;选项。

&#160;

我们需要加入一个View Controller到我们的项目，它将负责处理启动画面视图。在你的项目中加入一个新的UIViewController的子类文件。取名为SplashViewController，同时选择建立.h文件。
&#160;


&#160;


然后，我们要改变AppDelegate以加载此View Controller而不是原来的Main View Controller。打开iTennisAppDelegate.h修改如下：
&#160;




&#160;


主要是将iTennisViewController替换为SplashViewController。接着，打开iTennisAppDelegate.m做如下修改：



&#160;


这里我们所作的也只是将iTennisViewController替换为SplashViewController。这是因为我们希望开始时加载启动页面而不是游戏主画面。这里需要注意的一个主要区别是我们分配了一个新的SplashViewController实例。我们不需要对iTennisViewController这样做是因为它是从nib文件中加载而由程序本身对它进行初始化的。由于我们是通过编程来建立SplashViewController(没有nib), 所以需要将其实例化。接着我们就要实现SplashView。打开SplashViewController.h加入以下代码：
&#160;



&#160;


我来解释一下我们到底做了什么。首先，我们看到一个NSTimer。它被用于在启动画面淡出到游戏主画面前启动画面保持显示的时间。接着，有一个UIImageView，它将提供启动画面的图像。

  


最后，我们看到iTennisViewController，这是被程序代理替换掉的视图控制器。我们将从启动视图中加载它。打开SplashViewController.m 加入下列代码：



&#160;


这只是用来合成所有的属性。在loadView方法中加入下面代码:
&#160;



&#160;
这里有很多新代码。首先，由于是通过编程而不是通过nib来加载视图，我们必须创建视图。我们使用运行程序的框架（frame）来建立一个新的视图。然后将SplashViewController的视图设定到这个刚建立的视图。我们必须建立一个框架来通知应用程序创建一个320&#215;480的视图。

&#160;

下面，我们用Splash.png图像创建splashImageView。我们还需要为这个图像创建一个框架。将此框架想象成一个空的容器，我们将把图像放在里面。接着，我们把imageview加入主视图。然后，我们通过将要加载的nib的文件传递给视图的主控制器而对其进行初始化。再把视图的alpha透明性设为0.0。这样，它就会完全不可见。最后，我们将其加到我们的视图中。请注意，此时它覆盖在splashImageView的上方，但由于alpha透明值为0.0，它仍然不可见。
&#160;
最后，启动定时器。这样，在调用&#8220;fadeScreen&#8221;方法前，启动屏幕将显示2秒钟。必须指出我是从这篇文章借用的fadescreen方法。

&#160;
加入下面代码:


此代码中包括很多动画。由于注解很详细，我就不过多涉猎了。在fadeScreen方法中视图淡出，然后调用finishedFading。finishFading方法使视图控制器的视图重新淡入。主视图将显示出来。记住从父视图中移除启动屏视图，否则你会看到奇怪的画面过度效果。

&#160;
今天就到这里。下次我将引入音频到游戏中。如果有什么问题与建议，write me on Twitter.

&#160;
源代码在这里下载。
&#160;
18 Mar 2009 原文见：iPhone Game Programming Tutorial Part 3 &#8211; Splash Screen 
]]></description>
			<content:encoded><![CDATA[<p>今天，我将介绍怎样为你的程序加一些&ldquo;铃和哨&rdquo;（注：指一些附加的花哨的东西）是你的游戏显得更完整。首先，我们为游戏增加一个启动页面。</p>
<p><span id="more-165"></span></p>
<p>&nbsp;</p>
<h3>创建启动页面</h4>
<p>&nbsp;</p>
<p>我们加入的启动页面将淡出到游戏主屏幕。你可以下载此图像加入到项目的<strong>Resources（资源）</strong>文件夹中。 请选择复选框中&ldquo;copy this image to the project&rsquo;s directory（拷贝此 图像至项目目录）&rdquo;选项。</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/03/splash.png"><img title="splash" src="http://icodeblog.com/wp-content/uploads/2009/03/splash.png" alt="splash" width="320" height="480"></a></p>
<p>&nbsp;</p>
<p>
我们需要加入一个View Controller到我们的项目，它将负责处理启动画面视图。在你的项目中加入一个新的<strong>UIViewController</strong>的子类文件。取名为<strong>SplashViewController</strong>，同时选择建立.h文件。</p>
<p>&nbsp;</p>
<div>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_01.png"><img title="screenshot_01" src="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_01.png" alt="screenshot_01" width="600" height="442"></a></p>
<p>&nbsp;</p>
</div>
<div>
<p>然后，我们要改变AppDelegate以加载此View Controller而不是原来的Main View Controller。打开<strong>iTennisAppDelegate.h</strong>修改如下：</p>
<p>&nbsp;</p>
</div>
<p></p>
<div>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_02.png"><img title="screenshot_02" src="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_02.png" alt="screenshot_02" width="466" height="194"></a></p>
<p>&nbsp;</p>
</div>
<div>
<p>主要是将iTennisViewController替换为SplashViewController。接着，打开<strong>iTennisAppDelegate.m</strong>做如下修改：</p>
</div>
<div>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_03.png"><img title="screenshot_03" src="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_03.png" alt="screenshot_03" width="418" height="365"></a></p>
<p>&nbsp;</p>
</div>
<div>
<p>这里我们所作的也只是将iTennisViewController替换为SplashViewController。这是因为我们希望开始时加载启动页面而不是游戏主画面。这里需要注意的一个主要区别是我们分配了一个新的SplashViewController实例。我们不需要对iTennisViewController这样做是因为它是从nib文件中加载而由程序本身对它进行初始化的。由于我们是通过编程来建立SplashViewController(没有nib), 所以需要将其实例化。接着我们就要实现SplashView。打开<strong>SplashViewController.h</strong>加入以下代码：</p>
<p>&nbsp;</p>
</div>
<div>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_04.png"><img title="screenshot_04" src="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_04.png" alt="screenshot_04" width="406" height="231"></a></p>
<p>&nbsp;</p>
</div>
<div>
<p>我来解释一下我们到底做了什么。首先，我们看到一个NSTimer。它被用于在启动画面淡出到游戏主画面前启动画面保持显示的时间。接着，有一个UIImageView，它将提供启动画面的图像。</p>
<p>
  </p>
</div>
<div>
<p>最后，我们看到<strong>iTennisViewController</strong>，这是被程序代理替换掉的视图控制器。我们将从启动视图中加载它。打开<strong>SplashViewController.m</strong> 加入下列代码：</p>
</div>
<div>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_05.png"><img title="screenshot_05" src="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_05.png" alt="screenshot_05" width="301" height="25"></a></p>
<p>&nbsp;</p>
</div>
<div>
<p>这只是用来合成所有的属性。在<strong>l</strong><strong>oadView</strong>方法中加入下面代码:</p>
<p>&nbsp;</p>
</div>
<div><a href="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_07.png"><img title="screenshot_07" src="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_07.png" alt="screenshot_07" width="761" height="259"></a></div>
<div>
<p>&nbsp;</p>
<p>这里有很多新代码。首先，由于是通过编程而不是通过nib来加载视图，我们必须创建视图。我们使用运行程序的框架（frame）来建立一个新的视图。然后将SplashViewController的视图设定到这个刚建立的视图。我们必须建立一个框架来通知应用程序创建一个320&#215;480的视图。</p>
</div>
<p>&nbsp;</p>
<div>
下面，我们用Splash.png图像创建splashImageView。我们还需要为这个图像创建一个框架。将此框架想象成一个空的容器，我们将把图像放在里面。接着，我们把imageview加入主视图。然后，我们通过将要加载的nib的文件传递给视图的主控制器而对其进行初始化。再把视图的alpha透明性设为0.0。这样，它就会完全不可见。最后，我们将其加到我们的视图中。请注意，此时它覆盖在splashImageView的上方，但由于alpha透明值为0.0，它仍然不可见。</p>
<p>&nbsp;</p>
<p>最后，启动定时器。这样，在调用&ldquo;fadeScreen&rdquo;方法前，启动屏幕将显示2秒钟。必须指出我是从<a href="http://www.iphonedevsdk.com/forum/iphone-sdk-development/12998-how-fade-between-views-transitioning-through-black.html" onclick="pageTracker._trackPageview('/outgoing/www.iphonedevsdk.com/forum/iphone-sdk-development/12998-how-fade-between-views-transitioning-through-black.html?referer=http%3A%2F%2Ficodeblog.com%2Fcategory%2Fiphone-programming-tutorials%2F');">这篇文章</a>借用的fadescreen方法。
</div>
<p>&nbsp;</p>
<div>加入下面代码:</div>
<div><a href="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_08.png"><img title="screenshot_08" src="http://icodeblog.com/wp-content/uploads/2009/03/screenshot_08.png" alt="screenshot_08" width="578" height="317"></a></div>
<div>
此代码中包括很多动画。由于注解很详细，我就不过多涉猎了。在fadeScreen方法中视图淡出，然后调用finishedFading。finishFading方法使视图控制器的视图重新淡入。主视图将显示出来。记住从父视图中移除启动屏视图，否则你会看到奇怪的画面过度效果。
</div>
<p>&nbsp;</p>
<p>今天就到这里。下次我将引入音频到游戏中。如果有什么问题与建议，<a href="http://twitter.com/brandontreb" onclick="pageTracker._trackPageview('/outgoing/twitter.com/brandontreb?referer=http%3A%2F%2Ficodeblog.com%2Fcategory%2Fiphone-programming-tutorials%2F');">write me on Twitter</a>.
</p>
<p>&nbsp;</p>
<p>源代码在<a href="http://icodeblog.com/wp-content/uploads/2009/03/itennis-3.zip">这里下载</a>。</p>
<p>&nbsp;</p>
<h5>18 Mar 2009 原文见：<a href="http://icodeblog.com/2009/03/18/iphone-game-programming-tutorial-part-3-splash-screen/" rel="bookmark" title="Permanent Link to iPhone Game Programming Tutorial Part 3 &ndash; Splash Screen">iPhone Game Programming Tutorial Part 3 &ndash; Splash Screen </a></h5>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e4%b8%89-%e5%90%af%e5%8a%a8%e7%94%bb%e9%9d%a2/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone游戏编程教程之二-用户互动，简单AI，游戏逻辑</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%b8%b8%e6%88%8f/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e4%ba%8c-%e7%94%a8%e6%88%b7%e4%ba%92%e5%8a%a8%ef%bc%8c%e7%ae%80%e5%8d%95ai%ef%bc%8c%e6%b8%b8%e6%88%8f%e9%80%bb%e8%be%91</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%b8%b8%e6%88%8f/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e4%ba%8c-%e7%94%a8%e6%88%b7%e4%ba%92%e5%8a%a8%ef%bc%8c%e7%ae%80%e5%8d%95ai%ef%bc%8c%e6%b8%b8%e6%88%8f%e9%80%bb%e8%be%91#comments</comments>
		<pubDate>Tue, 17 Feb 2009 16:29:00 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[游戏]]></category>
		<category><![CDATA[教程]]></category>

		<guid isPermaLink="false">http://iphonegeek.zuesitech.com/?p=126</guid>
		<description><![CDATA[今天，我将讨论玩家互动，简单的游戏AI即游戏逻辑。还将探讨一下简单的碰撞检测以便检测到什么时候球碰到球拍。根据大家要求，我还会在教程最后加入一些“挑战”以改进一些更高级的创意。首先打开第一部分的代码&#8230; 
 
&#160;
用户互动
&#160;
我们首先要实现的是用户互动。我们所需要做的只是将球拍的X位置移动到用户触摸的X位置。这是很简单的方法，我们还可以做得更好（我将这部分挑战放在教程的最后 ）。打开iTennisViewController.m加入下面代码：     
&#160;


&#160;
 就像上一篇教程一样，我们要重载touchesMoved方法。此方法在用户在屏幕上“拖动”手指时被触发。首先，我在touchesBegan中加入“else if”语句，当游戏处于运行状态时简单地将所有事件转发到touchesMoved中。touchesMoved中前两行是检测用户触屏的位置。接着，我们根据用户触屏X位置及黄色球拍（玩家球拍）Y位置创建 一个新的CGPoint。Objective-C不允许racquet_yellow.center.x = location.x。这可能是因为CGpiont不可改变（不可编辑）。最后，将玩家球拍的中点设置到新的位置。

&#160;
碰撞检测
&#160;
*更新, 有读者指出有更简单的碰撞检测方法。将下列代码加入到iTennisViewController.m 的gameLoop方法中：     
&#160;
    
&#160;
 苹果已经提供我们一个十分方便的方法检测对象frame是否碰撞。它就是CGRectIntersectsRect。我们只是简单地提交球和球拍的frame给此方法。当球与球拍碰撞时，我们将Y速度反向。下一个if语句也是必需的，因为有时球被向反向移动的球拍“截留”住了而不会移动。因此，我们应保证球速度只当球在球拍前方时反向。（注：NSLog仅用调试）。

&#160;
简单游戏AI
&#160;
下面 ，我们将讨论怎样加入简单的AI，让电脑选手与我们玩iTennis。你们可能知道一个不错的AI设计牵涉了多少工作。我可以不停地介绍数学，哲学，试探法等，但我不会这么做。我只是介绍一种超级菜鸟级的游戏AI。基本上说，电脑将“观察”球并向其方向移动，希望能击打到它。
&#160;
首先，我们需要定义一个常量，它决定了电脑的移动速度。 在iTennisViewController.m顶部加入如下定义：
&#160;
     
&#160;
你测试时，可以调整这个数值。它定义了电脑选手为到达球的位置能移动得多快。这个数值越大，电脑选手将越“强”。如果这个数值足够大的话，那么电脑将不可战胜。现在，在碰撞检测代码后加入以下代码： 
&#160;
     
&#160;
第一个“if”语句是为了给电脑增加点难度，检查球是否处于“它”的半场。如果球不在它的半场，电脑将不会有任何动作。你可以省略这条语句，那就成了另一个有趣的游戏了。下一条“if”语句检查球中心的X与球拍中心的X是否不同。如果球在电脑球拍的右方，电脑球拍的X坐标将增大kCompMoveSpeed。如果球在电脑球拍的左方，电脑球拍的X坐标将减小kCompMoveSpeed。
&#160;
现在应该很清楚kCompMoveSpeed变量是怎样影响电脑的表现了吧&#8230;&#8230;
&#160;
你可以按“Build and Go”来看看游戏的表现吧。你可以看到电脑会做出反应并在大部分时间内击打到球。但为了游戏更有趣，还剩下最后一部分：记分。
&#160;
游戏机制：记分 
&#160;
我们需要一种方式来保存分数。这实际上是一种更简单的碰撞检测。我们将检查球是否碰到后墙。 首先，我们定义几个变量和方法。打开iTennisViewController.h，添加下列高亮的代码：
&#160;
      
&#160;
 我们需要一个代表分数的整数，当电脑和玩家得分时，我们会把分数加上。 另外我们还需要一个“reset”函数，调用它会将球复位到屏幕的中心。我们还需要定义另一个变量。将下面各行加入到iTennisViewController.m的顶部：

&#160;
 
&#160;
这个变量的意思应该很清楚，它定义了需要获胜的分数。为了加快游戏进程，我只是将其赋值为5。下面，我们检查是电脑还是玩家得分。在AI代码后，加入下面代码： 
&#160;
 
&#160;
首先我们看到两条if语句。它们只是检查球是否碰到/超过屏幕的顶部或底部。如果球超过顶部，玩家将得分。如果球超出底部，电脑将得分。如果你是编程新手的话，下面一行可能有些奇怪。我们调用reset函数，但是我们传递的表达式是什么意思？
&#160;
如果你看一下reset的定义，你就会知道，它接受一个代表游戏是否结束的BOOL值。它可以为true或false。我们实际上只是传递true或false给函数。所以，当player_score_value变量小于5时，(player_score_value &#62;= [...]]]></description>
			<content:encoded><![CDATA[<p align="left">今天，我将讨论玩家互动，简单的游戏AI即游戏逻辑。还将探讨一下简单的碰撞检测以便检测到什么时候球碰到球拍。根据大家要求，我还会在教程最后加入一些“挑战”以改进一些更高级的创意。首先打开第一部分的代码&#8230; </p>
<p> <span id="more-126"></span>
<p>&#160;</p>
<h3 align="left"><strong>用户互动</strong></h3>
<p>&#160;</p>
<p align="left">我们首先要实现的是用户互动。我们所需要做的只是将球拍的X位置移动到用户触摸的X位置。这是很简单的方法，我们还可以做得更好（我将这部分挑战放在教程的最后 ）。打开<strong>iTennisViewController.m</strong>加入下面代码：     </p>
<p>&#160;</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/02/screenshot_01.jpg"><img title="screenshot_01" alt="screenshot_01" src="http://icodeblog.com/wp-content/uploads/2009/02/screenshot_01.jpg" width="442" height="218" /></a></p>
<p align="left"></p>
<p>&#160;</p>
<p> 就像上一篇教程一样，我们要重载<strong>touchesMoved</strong>方法。此方法在用户在屏幕上“拖动”手指时被触发。首先，我在<strong>touchesBegan</strong>中加入“else if”语句，当游戏处于运行状态时简单地将所有事件转发到<strong>touchesMoved</strong>中。<strong>touchesMoved</strong>中前两行是检测用户触屏的位置。接着，我们根据用户触屏X位置及黄色球拍（玩家球拍）Y位置创建 一个新的CGPoint。Objective-C不允许racquet_yellow.center.x = location.x。这可能是因为CGpiont不可改变（不可编辑）。最后，将玩家球拍的中点设置到新的位置。
</p>
<p>&#160;</p>
<h3 align="left"><strong>碰撞检测</strong></h3>
<p>&#160;</p>
<p align="left">*更新, 有读者指出有更简单的碰撞检测方法。将下列代码加入到<strong>iTennisViewController.m</strong> 的gameLoop方法中：     </p>
<p>&#160;</p>
<p> <a href="http://icodeblog.com/wp-content/uploads/2009/02/screenshot_011.jpg"><img title="screenshot_011" alt="screenshot_011" src="http://icodeblog.com/wp-content/uploads/2009/02/screenshot_011.jpg" width="370" height="175" /></a>   </p>
<p>&#160;</p>
<p> 苹果已经提供我们一个十分方便的方法检测对象frame是否碰撞。它就是<strong>CGRectIntersectsRect</strong>。我们只是简单地提交球和球拍的frame给此方法。当球与球拍碰撞时，我们将Y速度反向。下一个if语句也是必需的，因为有时球被向反向移动的球拍“截留”住了而不会移动。因此，我们应保证球速度只当球在球拍前方时反向。（注：NSLog仅用调试）。
</p>
<p>&#160;</p>
<h3 align="left"><strong>简单游戏AI</strong></h3>
<p>&#160;</p>
<p align="left">下面 ，我们将讨论怎样加入简单的AI，让电脑选手与我们玩iTennis。你们可能知道一个不错的AI设计牵涉了多少工作。我可以不停地介绍数学，哲学，试探法等，但我不会这么做。我只是介绍一种超级菜鸟级的游戏AI。基本上说，电脑将“观察”球并向其方向移动，希望能击打到它。</p>
<p>&#160;</p>
<p align="left">首先，我们需要定义一个常量，它决定了电脑的移动速度。 在<strong>iTennisViewController.m</strong>顶部加入如下定义：</p>
<p>&#160;</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/02/picture-2.png">     <img title="picture-2" alt="picture-2" src="http://icodeblog.com/wp-content/uploads/2009/02/picture-2.png" width="156" height="20" /></a></p>
<p>&#160;</p>
<p>你测试时，可以调整这个数值。它定义了电脑选手为到达球的位置能移动得多快。这个数值越大，电脑选手将越“强”。如果这个数值足够大的话，那么电脑将不可战胜。现在，在碰撞检测代码后加入以下代码： </p>
<p>&#160;</p>
<p><a href="http://www.weebly.com/uploads/3/1/2/4/3124527/iphonegameprogramming-3.jpg"><img alt="http://icodeblog.com/wp-content/uploads/2009/02/picture-3.png" src="http://www.weebly.com/uploads/3/1/2/4/3124527/iphonegameprogramming-3.jpg" /></a>     </p>
<p>&#160;</p>
<p>第一个“if”语句是为了给电脑增加点难度，检查球是否处于“它”的半场。如果球不在它的半场，电脑将不会有任何动作。你可以省略这条语句，那就成了另一个有趣的游戏了。下一条“if”语句检查球中心的X与球拍中心的X是否不同。如果球在电脑球拍的右方，电脑球拍的X坐标将增大<strong>kCompMoveSpeed</strong>。如果球在电脑球拍的左方，电脑球拍的X坐标将减小<strong>kCompMoveSpeed</strong>。</p>
<p>&#160;</p>
<p>现在应该很清楚kCompMoveSpeed变量是怎样影响电脑的表现了吧&#8230;&#8230;</p>
<p>&#160;</p>
<p>你可以按“Build and Go”来看看游戏的表现吧。你可以看到电脑会做出反应并在大部分时间内击打到球。但为了游戏更有趣，还剩下最后一部分：记分。</p>
<p>&#160;</p>
<h3><strong>游戏机制：记分</strong> </h3>
<p>&nbsp;</p>
<p>我们需要一种方式来保存分数。这实际上是一种更简单的碰撞检测。我们将检查球是否碰到后墙。 首先，我们定义几个变量和方法。打开<strong>iTennisViewController.h</strong>，添加下列高亮的代码：</p>
<p>&#160;</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/02/picture-4.png">     <br /><img title="picture-4" alt="picture-4" src="http://icodeblog.com/wp-content/uploads/2009/02/picture-4.png" width="398" height="450" /></a> </p>
<p>&#160;</p>
<p> 我们需要一个代表分数的整数，当电脑和玩家得分时，我们会把分数加上。 另外我们还需要一个“reset”函数，调用它会将球复位到屏幕的中心。我们还需要定义另一个变量。将下面各行加入到<strong>iTennisViewController.m</strong>的顶部：
</p>
<p>&#160;</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/02/picture-5.png"><img title="picture-5" alt="picture-5" src="http://icodeblog.com/wp-content/uploads/2009/02/picture-5.png" width="132" height="18" /></a> </p>
<p>&#160;</p>
<p>这个变量的意思应该很清楚，它定义了需要获胜的分数。为了加快游戏进程，我只是将其赋值为5。下面，我们检查是电脑还是玩家得分。在AI代码后，加入下面代码： </p>
<p>&#160;</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/02/picture-6.png"><img title="picture-6" alt="picture-6" src="http://icodeblog.com/wp-content/uploads/2009/02/picture-6.png" width="346" height="150" /></a> </p>
<p>&#160;</p>
<p>首先我们看到两条if语句。它们只是检查球是否碰到/超过屏幕的顶部或底部。如果球超过顶部，玩家将得分。如果球超出底部，电脑将得分。如果你是编程新手的话，下面一行可能有些奇怪。我们调用reset函数，但是我们传递的表达式是什么意思？</p>
<p>&#160;</p>
<p>如果你看一下reset的定义，你就会知道，它接受一个代表游戏是否结束的BOOL值。它可以为true或false。我们实际上只是传递true或false给函数。所以，当player_score_value变量小于5时，(player_score_value &gt;= kScoreToWin)为false，而当此变量到5时，表达式为true。 </p>
<p>&#160;</p>
<p>我们为什么要这样做？因为这样可以节省好几行代码并降低程序复杂度 。所以我们现在不需要if(player_score_value &gt;= kScoreToWin) ) [self reset:YES]; }else{[self reset:NO];}。明白了吗？</p>
<p>&#160;</p>
<p>下面，我们定义reset函数 。在<strong>iTennisViewController.m</strong>中加入下列代码： </p>
<p>&#160;</p>
<p><a href="http://icodeblog.com/wp-content/uploads/2009/02/picture-7.png"><img title="picture-7" alt="picture-7" src="http://icodeblog.com/wp-content/uploads/2009/02/picture-7.png" width="496" height="272" /></a></p>
<p>&#160;</p>
<p>首先我们暂停游戏。暂停游戏使“Tap to Begin”信息显示在屏幕上。然后，我们将球定位到屏幕中心。如果被传递的参数newGame为YES/true，我们需要做几件事。首先，通过比较电脑和玩家分数，我们要检查谁是赢家。然后，更新“tapToBegin”（标签变量）通知用户谁获胜。你也可以加多另一个标签作此用，但我只是循环使用“tapToBegin”标签。最后，因为要开始新游戏，我们将玩家和电脑的分数清零。</p>
<p>&#160;</p>
<p>如果newGame为NO/false，我们只需要复位tapToBegin，显示“Tap to Begin”。这只是为了更改tapToBegin中的信息，以防其还显示着像“Player/Computer wins！”（“玩家/电脑获胜！”）之类的信息。</p>
<p>&#160;</p>
<p>按“Build and Go”与电脑进行一场“史诗般”的iTennis决战吧！源代码在<a href="http://icodeblog.com/wp-content/uploads/2009/02/itennis-21.zip">此</a>下载。</p>
<p>&#160;</p>
<h3><strong>如约，这里有一些挑战</strong></h3>
<p>&#160;</p>
<ul type="disc">
<li>改进用户互动 – 当用户触屏时，球拍并不直接移动到触屏的位置，而是向触屏的方向移动 </li>
<li>改进碰撞检测 – 当球碰到球拍时，使用一些简单的物理学原理使球拍的速度影响球的速度（和方向） </li>
<li>改进AI – 为AI增加一些随机性，使它能尽量“预测”球的运行轨迹 </li>
<li>改进记分系统 &#8211; 使用网球记分 15, 30 , 等&#8230;&#8230; </li>
<li>改进记分系统 &#8211; 你必须赢两分以上 </li>
</ul>
<p>&#160;</p>
<p align="left">请继续关注我们的教程，我将介绍游戏音频，启动画面，“关于&#8230;&#8230;”以及其他部分&#8230;&#8230;.</p>
<p>&#160;</p>
<h5 align="left"><strong>18/02/2009 </strong><strong>原文见：</strong><a title="Permanent Link to iPhone Game Programming Tutorial Part 2- User Interaction, Simple AI, Game Logic" href="http://icodeblog.com/2009/02/18/iphone-game-programming-tutorial-part-2-user-interaction-simple-ai-game-logic/"><strong>iPhone Game Programming Tutorial Part 2- User Interaction, Simple AI, Game Logic</strong></a><strong>&#160;&#160; 翻译：</strong>bagusflyer</h5>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%b8%b8%e6%88%8f/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e4%ba%8c-%e7%94%a8%e6%88%b7%e4%ba%92%e5%8a%a8%ef%bc%8c%e7%ae%80%e5%8d%95ai%ef%bc%8c%e6%b8%b8%e6%88%8f%e9%80%bb%e8%be%91/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>iPhone游戏编程教程之一</title>
		<link>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%b8%b8%e6%88%8f/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e4%b8%80</link>
		<comments>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%b8%b8%e6%88%8f/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e4%b8%80#comments</comments>
		<pubDate>Wed, 14 Jan 2009 16:03:00 +0000</pubDate>
		<dc:creator>bagusflyer</dc:creator>
				<category><![CDATA[游戏]]></category>
		<category><![CDATA[教程]]></category>

		<guid isPermaLink="false">http://iphonegeek.zuesitech.com/?p=123</guid>
		<description><![CDATA[这是此系列教程的第一部分，我将从最基本开始教大家怎样编写一个iPhone游戏。众所周知，OpenGL和Quartz的学习不是那么简单的。本教程将简化开发的过程而不会使用这两种技术。我们将使用UIImageView作为图像部分。 


在此教程系列中，我将教大家有关iPhone游戏编程的方方面面。游戏包括图形，音效，游戏逻辑以及简单的电脑AI。 

这是此系列教程的第一部分，我将从最基本开始教大家怎样编写一个iPhone游戏。众所周知，OpenGL和Quartz的学习不是那么简单的。本教程将简化开发的过程而不会使用这两种技术。我们将使用UIImageView作为图像部分。 


在此教程系列中，我将教大家有关iPhone游戏编程的方方面面。游戏包括图形，音效，游戏逻辑以及简单的电脑AI。 

这是此系列教程的第一部分，我将从最基本开始教大家怎样编写一个iPhone游戏。众所周知，OpenGL和Quartz的学习不是那么简单的。本教程将简化开发的过程而不会使用这两种技术。我们将使用UIImageView作为图像部分。 


在此教程系列中，我将教大家有关iPhone游戏编程的方方面面。游戏包括图形，音效，游戏逻辑以及简单的电脑AI。 
这是此系列教程的第一部分，我将从最基本开始教大家怎样编写一个iPhone游戏。众所周知，OpenGL和Quartz的学习不是那么简单的。本教程将简化开发的过程而不会使用这两种技术。我们将使用UIImageView作为图像部分。 


在此教程系列中，我将教大家有关iPhone游戏编程的方方面面。游戏包括图形，音效，游戏逻辑以及简单的电脑AI。]]></description>
			<content:encoded><![CDATA[<p align="left">这是此系列教程的第一部分，我将从最基本开始教大家怎样编写一个iPhone游戏。众所周知，OpenGL和Quartz的学习不是那么简单的。本教程将简化开发的过程而不会使用这两种技术。我们将使用UIImageView作为图像部分。 </p>
<p>&nbsp;</p>
<p align="left">在此教程系列中，我将教大家有关iPhone游戏编程的方方面面。游戏包括图形，音效，游戏逻辑以及简单的电脑AI。 </p>
<p> <span id="more-123"></span>
<p>&nbsp;</p>
<p align="left">我们将编写的游戏叫iTennis。它实际上是一个以网球为主题的乒乓游戏。它将遵循乒乓游戏的所有规则和逻辑。我选择其作为第一个游戏教程是不需要任何特殊动画效果的。如果大家有兴趣，我将在以后的系列中更加深入，介绍一个更加复杂的游戏。下面是游戏的截图：    </p>
<p>&nbsp;</p>
<p align="left"><img border="0" alt="screenshot_011" src="http://icodeblog.com/wp-content/uploads/2009/01/screenshot_011.jpg" width="386" height="742" />    </p>
<p>&nbsp;</p>
<p>下面是项目需要的图像。按图标下载压缩的图像文件。    </p>
<p>&nbsp;</p>
<p align="left"><a href="http://icodeblog.com/wp-content/uploads/2009/01/itennis_images.zip"><img border="0" alt="iTennis_Images.zip" src="http://icodeblog.com/wp-content/uploads/2009/01/packageicon.png" width="123" height="113" /></a></p>
<p>&nbsp;</p>
<p align="left">打开Xcode建立一个View Based应用程序，取名为iTennis。 </p>
<p>&nbsp;</p>
<p align="left"><img border="0" alt="screenshot_01" src="http://icodeblog.com/wp-content/uploads/2009/01/screenshot_01.jpg" width="600" height="442" />    </p>
<p>&nbsp;</p>
<p align="left">加压下载的图像文件，将其拖放到项目下的Resources(资源)文件夹。完成后，资源文件夹应该像这样。 </p>
<p>&nbsp;</p>
<p align="left"><img border="0" alt="screenshot_02" src="http://icodeblog.com/wp-content/uploads/2009/01/screenshot_02.jpg" width="240" height="306" /></a></p>
<p>&nbsp;</p>
<p align="left">&#160;</p>
<p align="left">现在可以开始编写代码了。为了在代码中与我们的图像互动，我们首先需要建立一个IBOutlet链接。我们还需要加入一些游戏变量以便在可以在教程中使用。打开iTennisVeiwController.h加入以下代码： </p>
<p>&nbsp;</p>
<p align="left"><img border="0" alt="screenshot_05" src="http://icodeblog.com/wp-content/uploads/2009/01/screenshot_05.jpg" width="397" height="405" />     </p>
<p>&nbsp;</p>
<p align="left">如你所见，我们有好些IBOutlet。这是因为我们需要与许多对象互动。暂时先忽略ballVelocity和gameState变量。现在，我们可以开始建立我们的用户界面了。双击iTennisViewController.xib在Interface Builder中打开。下面是一个视频介绍怎样建立界面。 </p>
<p>&nbsp;</p>
<div style="text-align: left"> <script type="text/javascript" src="http://icodeblog.com/wp-includes/js/jquery/jquery.js?ver=1.3.2"></script><script type="text/javascript" src="http://icodeblog.com/wp-content/plugins/quicktime-embed/qtobject.js"></script> <script type="text/javascript">
<!--
	var myQTObject = new QTObject("http://icodeblog.com/wp-content/uploads/2009/01/Game_1.mov", "Game_1", "640", "432"); 
	myQTObject.addParam("autostart","false");
	myQTObject.addParam("targetcache","true");
	myQTObject.write();
//--></p>
<p></script><noscript></noscript></div>
</p>
<p>&nbsp;</p>
<p align="left">现在你已经做好了链接，关闭Interface Builder返回Xcode。我们需要设定一些常量。你可以硬编码这些数值，但是将它们定为常量是你在调整游戏架构时更易于改变。打开iTennisViewController.m，加入下列代码。 </p>
<p>&nbsp;</p>
<p align="left"><strong><img border="0" alt="screenshot_06" src="http://www.weebly.com/uploads/3/1/2/4/3124527/iphonegameprogramming-1.jpg" width="511" height="166" /></strong>     </p>
<p>&nbsp;</p>
<p align="left">我们来解释下这些常量的意义。前面两个是游戏的状态。我们用它们来确定屏幕上将显示什么。游戏是暂停？是在运行？还是处于标题画面？以后我们会加入更多的状态。下面两个变量是球运行的速度。由于游戏是2D的，只需要X和Y的速度作为它们的速度矢量。再下面一行（注：应该是@synthesize这一行）是用来自动产生getter和setter方法的变量。</p>
<p>&nbsp;</p>
<p align="left">现在，我们在viewDidLoad方法中加入下列代码： </p>
<p>&nbsp;</p>
<p align="left"><img border="0" alt="screenshot_07" align="textTop" src="http://www.weebly.com/uploads/3/1/2/4/3124527/iphonegameprogramming-2.jpg" width="570" height="126" /></p>
<p>&nbsp;</p>
<p align="left">首先，我们将游戏状态设定为暂停状态。这样在视图被加载后，游戏不会立即开始。接着，我们建立球速向量。调整前面定义的常量，可以使球运行更快或更慢些。最后，创建一个NSTimer的实例。第一个参数是时阶。在此，我们设置为0.05秒。调整此参数可以改变整个游戏的速度。下面一个参数是目标。此参数告诉定时器回调的位置。再下面的参数就是回调的名称了。简单地说，就是通知定时器每隔0.05秒调用一次self.gameLoop。在这里我们不用管userInfo参数。最后一个参数是告诉定时器重复执行。 </p>
<p>&nbsp;</p>
<p align="left">初始化后，我们来创建游戏循环。加入下面代码： </p>
<p>&nbsp;</p>
<p align="left"><img border="0" alt="screenshot_08" src="http://icodeblog.com/wp-content/uploads/2009/01/screenshot_08.jpg" width="609" height="263" />     </p>
<p>&nbsp;</p>
<p align="left">首先我们检查游戏是否处于运行状态（暂停状态时，不需要移动球）。如果游戏没有运行，tabToBegin标签将会被显示出来。我们先前定义的这个标签只是通知用户触动屏幕开始。如果游戏真正运行，我们会根据其速度向量来移动球。下面几行是边界检查。如果球到达屏幕边界，我们就会将其速度方向，这样球就会“来回弹跳”。没有这些代码，球就会飞出屏幕了。
<p>&nbsp;</p>
<p>最后我们还要加入的代码是touchesBegan方法。此方法是在游戏暂停时用来启动游戏的。加入下面代码： </p>
<p>&nbsp;</p>
<p align="left"><img border="0" alt="screenshot_09" src="http://icodeblog.com/wp-content/uploads/2009/01/screenshot_09.jpg" width="409" height="91" />     </p>
<p>&nbsp;</p>
<p align="left">这段代码首先检查游戏是否处于暂停状态。如果是，则隐藏tapToBegin标签并设定游戏为运行状态。游戏将启动。以后，我们将会在此函数中写入玩家球拍控制。 </p>
<p>&nbsp;</p>
<p align="left">最后，作为一个好的iPhone开发者，我们需要清除分配的资源。在dealloc方法中加入下面代码。 </p>
<p>&nbsp;</p>
<p align="left"><img border="0" alt="screenshot_10" src="http://icodeblog.com/wp-content/uploads/2009/01/screenshot_10.jpg" width="184" height="135" /></p>
<p>&nbsp;</p>
<p align="left">游戏开发教程系列第一部分到此结束。有什么问题，请留言。<u><a href="http://icodeblog.com/wp-content/uploads/2009/01/itennis.zip">这里</a></u>下载源码。 </p>
<p align="left">&#160;</p>
<p>&nbsp;</p>
<h5 align="left"><strong>原文出自：</strong><a title="Permanent Link to iPhone Game Programming Tutorial – Part 1" href="http://icodeblog.com/2009/01/15/iphone-game-programming-tutorial-part-1/"><strong>iPhone Game Programming Tutorial – Part 1 </strong></a></h5>
]]></content:encoded>
			<wfw:commentRss>http://www.iphone-geek.cn/%e7%bc%96%e7%a8%8b/%e6%b8%b8%e6%88%8f/iphone%e6%b8%b8%e6%88%8f%e7%bc%96%e7%a8%8b%e6%95%99%e7%a8%8b%e4%b9%8b%e4%b8%80/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
<enclosure url="http://icodeblog.com/wp-content/uploads/2009/01/Game_1.mov" length="14481335" type="video/quicktime" />
		</item>
	</channel>
</rss>
