我正在尝试使用 SurfaceView,但 lockCanvas(null)
令人困惑,并且当我退出 Activity 时应用程序会卡住。另外,即使我使用的教程运行得很好,也没有显示任何内容,而且我不明白我做错了什么。请帮忙。
最佳答案
解决方案可能是未调用 setWillNotDraw(false);
。
因此,正常工作的引用实现如下:
public class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback
{
private SurfaceHolder holder;
private MyThread myThread;
private GameController gameController;
private Paint paint;
private int width;
private int height;
public GameSurfaceView(Context context, GameController gameController, int width, int height)
{
super(context);
holder = getHolder();
holder.addCallback(this);
this.gameController = gameController;
this.width = width;
this.height = height;
paint = new Paint();
//initialize paint object parameters
setWillNotDraw(false); //this line is very important!
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
}
@Override
// This is always called at least once, after surfaceCreated
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
if (myThread == null)
{
myThread = new MyThread(holder, gameController);
myThread.setRunning(true);
myThread.start();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
myThread.setRunning(false);
while (retry)
{
try
{
myThread.join();
retry = false;
}
catch (InterruptedException e)
{
Log.d(getClass().getSimpleName(), "Interrupted Exception", e);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
System.out.println(event.getX() + " " + event.getY());
gameController.onTouchEvent(event); //handle user interaction
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawText("Hello world!", width/20, 20, paint);
gameController.draw(canvas);
}
public Thread getThread()
{
return thread;
}
public class MyThread extends Thread
{
private SurfaceHolder holder;
private boolean running = false;
private GameController gameController;
public MyThread(SurfaceHolder holder, GameController gameController)
{
this.holder = holder;
this.gameController = gameController;
}
@Override
public void run()
{
Canvas canvas = null;
while (running)
{
gameController.update(); //update the time between last update() call and now
try
{
canvas = holder.lockCanvas(null);
synchronized (holder)
{
postInvalidate();
}
}
finally
{
if (canvas != null)
{
holder.unlockCanvasAndPost(canvas);
}
}
}
}
public void setRunning(boolean b)
{
running = b;
}
}
}
表面本身并不真正想要回答它的宽度和高度是多少,因此如果我们从外部获取它的测量值,并从外部将其提供给我们的自定义 View ,会更容易:
//Fragment onCreateView()
Display display = getActivity().getWindowManager().getDefaultDisplay();
RelativeLayout rl = (RelativeLayout)view.findViewById(R.id.gameplay_container);
rl.addView(new GameSurfaceView(this.getActivity().getApplicationContext(), gameController, display.getWidth(), display.getHeight()));
return view;
}
现在我们可以从我们自己的线程中绘制到 SurfaceView 上,并且我们还可以将所有与游戏相关的逻辑分离到 GameController 中。 GameController 负责输入处理和游戏事件更新,如下所示:
public void update()
{
long delta = getTimeManager().getDeltaTime(System.currentTimeMillis());
long timeChunk;
if (isGameOver == false)
{
for (long i = 0; i < delta; i += 20)
{
long iNext = i + 20;
if (iNext > delta)
{
timeChunk = delta - i;
}
else
{
timeChunk = iNext - i;
}
// ...update game entities based on the miliseconds provided in timeChunk
}
获取时间增量(自上次更新以来耗时)如下:
long temp = currentTimeMillis - oldTime;
this.oldTime = currentTimeMillis;
return temp;
希望对你以后有帮助:)
关于android - 使用自定义SurfaceView和线程进行Android游戏编程(示例),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24890900/