我正在开发一个Android游戏引擎,使用SurfaceView绘制Bitmaps,使用与LunarLander类似的框架。我的主要游戏引擎活动设置布局,使 显示一个SurfaceView扩展类,如下所示:
super.onCreate(savedInstanceState);
setContentView(R.layout.ss_layout);
SSSurfaceView ssSurfaceView = (SSSurfaceView)findViewById(R.id.surface_view);
SSSurfaceView.SSViewThread renderThread =
(SSSurfaceView.SSViewThread) ssSurfaceView.getThread();
findViewById方法成功返回我的SurfaceView扩展类的实例,并且我能够运行我在类中定义的线程,该类在此方法中创建,类构造函数:
public SSSurfaceView(Context context, AttributeSet attributes)
{
super(context, attributes);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
thread = new SSViewThread(holder, context);
}
构造函数应获取对相关SurfaceHolder的引用,然后将其传递给线程构造函数。我开始在线程运行方法中遇到一个问题,其中holder.lockCanvas(null)返回null。我在某处读到这可能意味着表面尚未创建,所以我使用在surfaceCreated回调中设置为true的布尔值添加了一个if语句。
public void run()
{
Canvas canvas = null;
try
{
canvas = holder.lockCanvas(null);
//I added the condition below
if(surfaceCreated)
{
drawAll(canvas);
}
}
catch(Exception e)
{
Log.wtf("SurfaceView", "exception");
}
finally
{
if(canvas != null)
{
holder.unlockCanvasAndPost(canvas);
}
}
}
这是回调:
public void surfaceCreated(SurfaceHolder holder)
{
surfaceCreated = true;
}
事实证明,SurfaceCreated永远不会被调用。我的应用程序显示灰色屏幕,不执行任何其他操作,因为drawAll方法永远不会迭代。这是要引导的layout.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.bostonwalker.sseng.SSSurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
编辑:这不是我的整个代码,我试图将我的示例限制在相关部分。线程在主循环中被调用,但是给定时间,回调永远不会触发。
编辑:这是在UI线程中迭代的循环:
while(!halt)
{
//EDIT: Changed from .run() to .start()
renderThread.start();
gameThread.start();
//Wait for both threads to proceed before continuing
try
{
renderThread.join();
gameThread.join();
}
catch (InterruptedException e)
{
//Do nothing
}
Thread.currentThread();
try
{
Thread.sleep(2);
}
catch (Exception e)
{
//Do nothing
}
}
答案 0 :(得分:1)
你的绘图线程没有循环 - 它只运行一次然后退出。 并且可能在第一次运行时尚未创建表面。
您需要将您当前拥有的代码放在某种循环中,例如(伪代码):
while(!done) {
lockTheCanvas();
drawAFrame();
unlockTheCanvas();
sleep(FRAME_INTERVAL);
}
然后,您需要通过设置&#34; done&#34;在适当的时间终止线程。为真; 请注意,您需要sleep(),否则,您的线程将占用cpu,并且永远不会终止。