<?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>西瓜田 &#187; 手机游戏</title>
	<atom:link href="http://blog.thpiano.com/?feed=rss2&#038;tag=%E6%89%8B%E6%9C%BA%E6%B8%B8%E6%88%8F" rel="self" type="application/rss+xml" />
	<link>http://blog.thpiano.com</link>
	<description>无复洛城东</description>
	<lastBuildDate>Tue, 19 Jan 2021 03:54:37 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>Cocos2d-x在android开发下的帧数控制</title>
		<link>http://blog.thpiano.com/?p=866</link>
		<comments>http://blog.thpiano.com/?p=866#comments</comments>
		<pubDate>Fri, 31 May 2013 08:50:11 +0000</pubDate>
		<dc:creator>suika</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[android游戏开发]]></category>
		<category><![CDATA[cocos2d-x]]></category>
		<category><![CDATA[cocos2dx]]></category>
		<category><![CDATA[sleep]]></category>
		<category><![CDATA[帧数控制]]></category>
		<category><![CDATA[手机游戏]]></category>
		<category><![CDATA[游戏开发]]></category>

		<guid isPermaLink="false">http://blog.thpiano.com/?p=866</guid>
		<description><![CDATA[自从人参第一次面试悲剧以后决定多补linux，顺手在linux下写点代码 于是就瞄准了cocos2dx这个框架，写个android下的小游戏 顺便给大家做下效率参考： 手机配置CPU 600Mhz，内存256M，显卡未知 以前用java下的opengles，大概每秒可以渲染16x16的纹理6000次 cocos2dx下面用的版本是2.1.4，自己做了个子弹池，全部用一个批次，在有纹理旋转的情况下每秒32000次 感觉30fps的话已经够用了！但是一接到手机上，发现fps怎么不受控制！？ 一路追到Cocos2dxRenderer.java里一览究竟： 12345678910111213141516171819202122232425262728public void onDrawFrame&#40;final GL10 gl&#41; &#123; &#160; &#160; /* &#160; &#160; &#160;* FPS controlling algorithm is not accurate, and it will slow down FPS &#160; &#160; &#160;* on some devices. So comment FPS controlling code. &#160; &#160; &#160;*/ &#160; &#160; &#160; &#160; /* &#160; &#160; final [...]]]></description>
			<content:encoded><![CDATA[<p>自从人参第一次面试悲剧以后决定多补linux，顺手在linux下写点代码<br />
于是就瞄准了cocos2dx这个框架，写个android下的小游戏<br />
顺便给大家做下效率参考：<br />
手机配置CPU 600Mhz，内存256M，显卡未知<br />
以前用java下的opengles，大概每秒可以渲染16x16的纹理6000次<br />
cocos2dx下面用的版本是2.1.4，自己做了个子弹池，全部用一个批次，在有纹理旋转的情况下每秒32000次<br />
感觉30fps的话已经够用了！但是一接到手机上，发现fps怎么不受控制！？</p>
<p>一路追到Cocos2dxRenderer.java里一览究竟：<span id="more-866"></span></p>
<div class="codecolorer-container java geshi" 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 /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> onDrawFrame<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> GL10 gl<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">/*<br />
&nbsp; &nbsp; &nbsp;* FPS controlling algorithm is not accurate, and it will slow down FPS<br />
&nbsp; &nbsp; &nbsp;* on some devices. So comment FPS controlling code.<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">/*<br />
&nbsp; &nbsp; final long nowInNanoSeconds = System.nanoTime();<br />
&nbsp; &nbsp; final long interval = nowInNanoSeconds - this.mLastTickInNanoSeconds;<br />
&nbsp; &nbsp; */</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// should render a frame when onDrawFrame() is called or there is a</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// &quot;ghost&quot;</span><br />
&nbsp; &nbsp; Cocos2dxRenderer.<span style="color: #006633;">nativeRender</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">/*<br />
&nbsp; &nbsp; // fps controlling<br />
&nbsp; &nbsp; if (interval &lt; Cocos2dxRenderer.sAnimationInterval) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; try {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // because we render it before, so we should sleep twice time interval<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Thread.sleep((Cocos2dxRenderer.sAnimationInterval - interval) / Cocos2dxRenderer.NANOSECONDSPERMICROSECOND);<br />
&nbsp; &nbsp; &nbsp; &nbsp; } catch (final Exception e) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; this.mLastTickInNanoSeconds = nowInNanoSeconds;<br />
&nbsp; &nbsp; */</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>原来是帧数控制部分被官方注释掉了，他们给的原因是“不精确，在某些设备上还会拖慢速度”</p>
<p>当然除了动这个java文件，其实也有其他的解决方案，比如说干脆用一个while死循环完完全全地轮询过去，但是这种情况下的耗电和cpu占用都令人难以接受；<br />
也可以直接在游戏逻辑部分用c++写自己的帧数控制，但是却丧失了可移植性（至少linux/win32下的精确帧数控制写法是不同的）<br />
所以不能这么轻易就放弃，还是要在这里好好动手改一下。</p>
<p>首先要提出批评，貌似cocos2dx在这个android帧数控制上一直都有问题。<br />
首先注意看Thread.sleep((Cocos2dxRenderer.sAnimationInterval - interval) / Cocos2dxRenderer.NANOSECONDSPERMICROSECOND); 这句话，在早期版本里他sleep的时间是目前的2倍（官方注释都被保留了下来作为证据= =），至于为啥要乘以2他也语焉不详了。<br />
后来也有使用者发现了这个问题，于是去掉了乘以2，确实有所改良。（<a href="http://www.cocos2d-x.org/boards/6/topics/25571">见此</a>）</p>
<p>不过现在的这个Cocos2dxRenderer.java里单纯去掉注释，还是不行，因为他interval（或是上一帧时间基准）的计算位置还是错的OTL……<br />
给他挪好位置，在没什么负载的情况下，终于可以稳定在指定帧数上了。但是在有负载的情况下，却出现了拖慢的问题：<br />
若是不启用帧数控制，则原本可同屏900子弹跑到35-40fps，若是启用帧数控制，连25帧都稳定不到了。<br />
损耗出在哪里呢？我将计时换成了System.nanoTime()，已确定该函数损耗不高，但依旧不行。<br />
问题出在sleep上。在java里，sleep本来就不是一个能够得到精确保证的计时函数，实际运行的时候，经过测试，精度至少是比15ms还要差的</p>
<p>所以我的解决方案是，<span style="color: #0000ff;">先使用sleep进行等待在当前精度下比较保险的较短时间；对于剩余的部分，再采用while+轮询等待来补足</span>。<br />
比如说，预计精度是15ms，当前帧要等待35ms，则sleep(20ms)，在sleep醒来之后，可以预计此时时间已经过了20-35ms，但不会超过35ms，于是剩下的部分就用while等过去。<br />
这样既能提高精度，又能够避免一直用循环等待而带来的高耗电和cpu占用。代码见下：</p>
<div class="codecolorer-container java geshi" 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 /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">long</span> ACCURACYNANOSECONDSPERSECOND <span style="color: #339933;">=</span> NANOSECONDSPERMICROSECOND <span style="color: #339933;">*</span> <span style="color: #cc66cc;">15</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//accuracy</span><br />
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">long</span> lastRenderingTime<span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> onDrawFrame<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> GL10 gl<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; Cocos2dxRenderer.<span style="color: #006633;">nativeRender</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">long</span> now <span style="color: #339933;">=</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">nanoTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">long</span> renderingElapsedTime <span style="color: #339933;">=</span> now <span style="color: #339933;">-</span> lastRenderingTime<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">long</span> timeToWait <span style="color: #339933;">=</span> Cocos2dxRenderer.<span style="color: #006633;">sAnimationInterval</span> <span style="color: #339933;">-</span> renderingElapsedTime<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// try to sleep for a relative short (but safe) time according to ACCURACYNANOSECONDSPERSECOND</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>timeToWait <span style="color: #339933;">&gt;</span> ACCURACYNANOSECONDSPERSECOND<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Athread+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Thread</span></a>.<span style="color: #006633;">sleep</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>timeToWait <span style="color: #339933;">-</span> ACCURACYNANOSECONDSPERSECOND<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ainterruptedexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">InterruptedException</span></a> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; e.<span style="color: #006633;">printStackTrace</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">while</span><span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">nanoTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> now <span style="color: #339933;">&lt;</span> timeToWait<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// wait for the rest time that smaller than ACCURACYNANOSECONDSPERSECOND</span><br />
&nbsp; &nbsp; lastRenderingTime <span style="color: #339933;">=</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">nanoTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>&nbsp; <br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>变量lastRenderingTime在onSurfaceCreated函数里初始化一下即可。<br />
最后效果确实是提高了，至少可以稳定在28-30帧之间，勉强算是可以接受啦</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.thpiano.com/?feed=rss2&#038;p=866</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
