我正在尝试使用SurfaceView,但lockCanvas(null)
令人困惑,当我退出活动时应用会冻结。此外,没有任何显示,即使我使用的教程工作得很好,我不明白我做错了什么。请帮忙。
答案 0 :(得分:1)
解决方案可能是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;
}
}
}
表面本身并不想回答它的宽度和高度,因此如果我们从外部获取测量结果,并从外部为我们的自定义视图提供它,则更容易:
//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;
}
现在我们可以从我们自己的Thread中绘制到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;
我希望以后会对你有所帮助:))