有多个类似我的问题,但这些问题对我没有帮助。
我在做游戏。游戏线程、SurfaceView 和 Activity 已经完成并运行至今。问题是画布没有重绘。启动时,它会在背景上绘制图标,但在每一次滴答声中,图标都不会移动(它应该每秒移动一次)。我想提一下,我从来不需要调用postInvalidate。我有一个工作示例,我从未调用它,但它在我当前的示例中不起作用(我不想更深入地研究它,因为我实际上不需要调用它)。我从我的工作示例中复制了当前代码,概念和实现方式完全相同,但我当前的代码没有刷新画布。当我在onDraw中记录绘图位置时方法,我看到它的坐标按预期每秒更新,所以我可以确定这是一个画布绘图问题。我已经搜索了几个小时,但没有发现与我的工作示例有什么不同(除了我使用的是另一个 Android 版本并且我没有扩展线程而是实现 Runnable,因为扩展线程是一种不好的风格。不过,我还扩展了线程以查看是否有任何区别,但这没有帮助)。我已经尝试使用canvas.drawColor(Color.BLACK)清理画布,但这也无济于事。我已经尝试使用背景颜色而不是每个刻度随机更改的背景图像,但它没有改变但始终保持不变。我发现第一次调用时画布的密度为(例如)240。第二次打勾后,画布密度始终为 0。我知道密度在这里对我没有帮助,但也许这是一个重要信息给某人。
这是重要的课程......
游戏布局,R.layout.game
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gameContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.mydomain.mygame.base.game.GameSurface
android:id="@+id/gameSurface"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:background="@drawable/background_game" >
</com.mydomain.mygame.base.game.GameSurface>
<!-- ...more definitions -->
</LinearLayout>
GameActivity(包含布局)
public class GameActivity extends Activity
{
@SuppressWarnings("unused")
private GameSurface gameSurface;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.game);
gameSurface = (GameSurface)findViewById(R.id.gameSurface);
//TODO on button click -> execute methods
}
}
GameSurface(登录 onDraw 显示每个刻度更新的坐标)
public class GameSurface extends SurfaceView implements SurfaceHolder.Callback
{
private GameThread thread;
protected final static int TICK_FREQUENCY = 100;// ms, stays always the same. It's a technical constant which doesn't change
private static final String TAG = GameSurface.class.getSimpleName();
public GameSurface(Context context, AttributeSet attrs)
{
super(context, attrs);
ShapeManager.INSTANCE.init(context);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
setFocusable(true); // make sure we get key events
thread = new GameThread(holder, this);
}
public void updateStatus()
{
GameProcessor.INSTANCE.updateShapes();
}
@Override
protected void onDraw(Canvas canvas)
{
for (Shape shape : GameProcessor.INSTANCE.getShapes())
{
Log.i(TAG, "getX()=" + shape.getX() + ", getY()=" + shape.getY());
canvas.drawBitmap(shape.getBitmap(), shape.getX(), shape.getY(), null);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
//will never invoked since we only operate in landscape
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
// start the thread here so we don't busy-wait in run
thread.setRunning(true);
new Thread(thread).start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
Log.i(TAG, "executing surfaceDestroyed()...");
thread.setRunning(false);
}
}
游戏线程
public class GameThread implements Runnable
{
private SurfaceHolder surfaceHolder;
private boolean running = false;
private GameSurface gameSurface;
private long lastTick;
public GameThread(SurfaceHolder surfaceHolder, GameSurface gameSurface)
{
this.surfaceHolder = surfaceHolder;
this.gameSurface = gameSurface;
lastTick = System.currentTimeMillis();
}
@Override
public void run()
{
Canvas canvas;
while (running)
{
canvas = null;
if (System.currentTimeMillis() > lastTick + GameSurface.TICK_FREQUENCY)
{
long timeDifference = System.currentTimeMillis() - (lastTick + GameSurface.TICK_FREQUENCY);
try
{
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder)
{
gameSurface.updateStatus();
gameSurface.draw(canvas);
}
}
finally
{
if (canvas != null)
{
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
lastTick = System.currentTimeMillis() - timeDifference;
}
}
}
public void setRunning(boolean running)
{
this.running = running;
}
}
任何想法为什么此代码不更新我的画布?我无法解释。我没有发布ShapeManager和GameProcessor ,因为它们与问题没有任何关系(它们只加载和控制游戏的当前状态和速度)。
[更新]
我发现在游戏线程开始之前调用了 onDraw()。这意味着画布在线程使用它之前被传递给这个方法。有趣的是,线程启动后,它总是使用相同的画布,但不是第一次传递的画布引用。虽然canvas = surfaceHolder.lockCanvas(null); 每个刻度都分配,它始终是相同的参考,但它不是原始参考。在我的一个工作示例中,引用始终相同,因为我在构造函数初始化时创建位图。在我当前的实现中我不能这样做,因为我必须使用从 onMeasure() 获得的值进行计算,该值比构造函数调用晚得多。
我试图以某种方式将原始画布传递给线程,但引用仍然发生变化。同时我认为这是问题所在,但我还不知道如何解决它。