Vla*_*tin 3 java android frame-rate surfaceview
我正在尝试为 Android 创建一个 2d 游戏,目前我正在努力实现大约 30 fps 的恒定 fps(我认为 30 对手机游戏来说已经足够了)。我正在使用 SurfaceView 和一个非常直接的游戏循环:
while (isOk==true)
{
if (!holder.getSurface().isValid()) continue;
c = holder.lockCanvas();
update();
draw(c);
holder.unlockCanvasAndPost(c);
t2= System.currentTimeMillis();
all++;
if ( mspf /* miliseconds per frame, and it's set to 1000/30 */ -(t2-t1) > 0 )
{
try {
t.sleep(mspf-(t2-t1));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
Log.w("Super",String.valueOf(mspf-(t2-t1))+ " o " + String.valueOf(++total)+ "out of " +String.valueOf(all));
t1=Math.max( t1+mspf, t2);
}
Run Code Online (Sandbox Code Playgroud)
这是游戏循环。正如您可能已经注意到的,我使用 Log.w 来查看我有多少帧剩余时间可以用于 Thread.sleep。结果并没有那么好。我有大约 10-25% 的帧超过 1000/30 毫秒可以运行:
09-07 00:00:39.069:W/Super(28328):-1 o 4395out of 16353
09-07 00:00:39.109:W/Super(28328):-1 o 4396out of
163054 0 :39.209: W/Super(28328): 0 o 4397out of 16357
09-07 00:00:40.269: W/Super(28328): -4 o 4398out of 16389
09-07: 00/Super(2009) 28328): -3 o 4399out of 16390
09-07 00:00:40.339: W/Super(28328): -4 o 4400out of 16391
09-07 00:00:40.378: W/24o: 4401out of 16392
09-07 00:00:40.409: W/Super(28328): -5 o 4402out of 16393
09-07 00:00:40.459: W/Super(28328): -837 o
4 00:00:40.499:W/Super(28328):-7 o 4404out of 16395
09-07 00:00:40.529:W/Super(28328):-3 o 4405out of 16396
09-07 00:00:40.569:W/Super(28328):-5 o 4406out of 16397
09-07 00:00:40.609:W/Super(28328):-5 o 4407out of
19 :0098 0 :40.639: W/Super(28328): -3 o 4408out of 16399
09-07 00:00:40.679: W/Super(28328): -3 o 4409out of 16400
09-07: 00/7019 (28328):16401 中的 -4 o 4410
在 draw 中,我没有那么多位图要绘制。(大约 15 个位图,包括一个着色器、一个用于某些效果的透明蒙版和一个缩放)。所有位图都从资源(仅限 PNG 文件)在 create 方法中加载。
public void draw(Canvas c)
{
c.drawBitmap(background,0,0,null);
c.drawBitmap(m_image.get(m_cn),400 , 100, test);
c.drawBitmap(start_menu,10 ,10 , test);
c.drawBitmap(inventory_menu, 200 , 10, test);
c.drawBitmap(shop_menu,400 , 10, test);
c.drawBitmap(options_menu, 10 , 300, test);
c.drawBitmap(facebook_menu,200 , 300, test);
light.drawColor(Color.TRANSPARENT, Mode.CLEAR);
light_matrix.setScale(scale_factor, scale_factor);
light_matrix.postTranslate(light_x-mask_aux.getWidth()/2*scale_factor, light_y-mask_aux.getHeight()/2*scale_factor);
light.drawBitmap(mask_aux, light_matrix, test);
copy_the_screen.drawBitmap(buffer.get(b_activ),0,0,test);
sh = new BitmapShader(screen_copy,Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
pnt.setShader(sh);
c.drawARGB(200, 0, 0,0);
c.drawBitmap(mask,0,0 ,pnt);
}
Run Code Online (Sandbox Code Playgroud)
update 方法对复杂性没有任何意义,因此在这两个函数中需要做一些事情才能实现更好的 fps。帮助我,请原谅我的英语不好。
好的 。更新功能是这样的:
public void update()
{
m_time++;
if (m_time==2)
{
m_time=0;
m_cn++;
if (m_cn==4)m_cn=0;
}
if (touched==true)
{
light_x=t_x;
light_y=t_y;
scale_factor=t_y/150;
}
}
Run Code Online (Sandbox Code Playgroud)
它只修改我从精灵中选择的位图。我没有包含字符所有位置的大位图,而是 4 个不同的位图。第二个“如果”指的是一个蒙版图像,它在我触摸的地方创建一个光球。我使用该 light_matrix 来缩放与 Y 坐标(点击事件的)成比例的光球。这就是我使用着色器来创建灯光效果的原因。在这里,看看 OnTouchEvent :
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
//I put this sleep method here because I noticed it was the lagging the game if i let it run
// without a sleep.
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// after sleep , i only check for events.
}
Run Code Online (Sandbox Code Playgroud)
小智 5
首先,每帧创建新对象是一种糟糕的技术,所以请看这条线:
sh = new BitmapShader(screen_copy,Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Run Code Online (Sandbox Code Playgroud)
并将其移动到构造函数(或在您初始化游戏的地方),我不确定您是否需要更改BitmapShader每一帧,因为 screen_copy 发生了变化,但是如果有一种方法可以避免每帧创建一个新帧,那就是最好的事物。
private BitmapShader sh;
@Override
public void surfaceCreated(SurfaceHolder holder)
{
//...
sh = new BitmapShader(screen_copy,Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
}
Run Code Online (Sandbox Code Playgroud)
draw 方法的其余部分看起来不错。
在onTouchEvent看起来很奇怪,我不知道你为什么会用Thread.sleep(int),但我怀疑这是一个大问题。
现在我仔细看看你的主循环,它看起来有点奇怪,尤其是这条线
t1=Math.max( t1+mspf, t2);
Run Code Online (Sandbox Code Playgroud)
我认为这就是一切发生的原因,让我重新编写您的主循环,您可以尝试并告诉我结果
while (isOk) /*you can skip the "==true" part*/
{
if (!holder.getSurface().isValid()) continue;
//Start Frame
t1 = System.currentTimeMillis();
//Canvas and drawing
c = holder.lockCanvas();
update();
draw(c);
holder.unlockCanvasAndPost(c);
//End Frame
t2= System.currentTimeMillis();
all++;
if ( t2 -t1 > mspf )
{
try {t.sleep(mspf-(t2-t1));}
catch (InterruptedException e) {e.printStackTrace();}
}
else
Log.w("Super",String.valueOf(mspf-(t2-t1))+ " o " + String.valueOf(++total)+ "out of " +String.valueOf(all));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5932 次 |
| 最近记录: |