为什么不是';t view.invalidate立即在我的android游戏中重新绘制屏幕

为什么不是';t view.invalidate立即在我的android游戏中重新绘制屏幕,android,Android,我正在尝试制作一款android游戏 我有一个游戏类,可以扩展活动并处理所有用户输入。然后我有一个missionView类,它扩展了view,并在屏幕上绘制了标高 当用户单击门时,我想添加一些动画 发生的事情是:游戏调用door.open。更改状态,以便view.onDraw函数将门半开。游戏调用view.invalidate,这将重新绘制屏幕。然后游戏暂停半秒钟。然后它叫门,再开门。第二次调用该函数时,它会更改状态,以便view.onDraw函数将门完全打开。然后游戏再次调用view.inva

我正在尝试制作一款android游戏

我有一个游戏类,可以扩展活动并处理所有用户输入。然后我有一个missionView类,它扩展了view,并在屏幕上绘制了标高

当用户单击门时,我想添加一些动画

发生的事情是:游戏调用door.open。更改状态,以便view.onDraw函数将门半开。游戏调用view.invalidate,这将重新绘制屏幕。然后游戏暂停半秒钟。然后它叫门,再开门。第二次调用该函数时,它会更改状态,以便view.onDraw函数将门完全打开。然后游戏再次调用view.invalidate

问题是它在进入view.invalidate时不会重新绘制屏幕。如果在该行上设置断点并运行调试器并单击“单步执行”,则不会单步执行我的view.onDraw函数。它甚至不能向我显示它正在执行的代码

我得到的是: 门类别:

public boolean open()
{
   if (doorState == DoorState.Closed)
   {
       doorState = DoorState.Opening;

       return true;
   }
   else if (doorState == DoorState.Opening)
   {
        doorState = doorState.Open;
        return true;
   }
   else
   {
      return false;
   }
}
游戏类别:

if (tile instanceof DoorTile)
{
    DoorTile doorTile = (DoorTile) tile;
    Door door = doorTile.getDoor();

    if (door.isClosed())
    {
        door.open();
        selectedEntity.openDoor();
        view.invalidate();    // This line does not work

        try 
        {
            Thread.sleep(500);
        } 
        catch (InterruptedException e1) 
        {
             // TODO Auto-generated catch block
             e1.printStackTrace();
        }
        door.open();

        // Handled touch event so break switch statement
        break;
     }
}
View#invalidate告诉系统在主线程空闲时重新绘制(通过onDraw)视图。也就是说,调用invalidate计划在所有其他即时工作完成后重新绘制视图。如果游戏类中的代码是从主线程调用的,并且它使该线程处于休眠状态,那么您不仅仅是暂停渲染,而是同时暂停输入处理(通常是个坏主意)。根据经验,除非你知道自己在做什么,否则不要睡一根你自己没有产生的线


如果你想让你的游戏逻辑周期性地延迟使用线程#sleep,那么在一个单独的线程中运行它,并使用view.postInvalidate()来通知主线程唤醒并调用onDraw。

对于游戏,我实际上会使用较低级别的图形访问。来自谷歌的消息就是一个很好的例子。基本上你需要做两件事:

  • 使用SurfaceView而不是View
  • 从SurfaceView获取处理程序
  • 将view.invalidate()替换为包含

    private void repaint() {
      Canvas c = null;
      try {
        c = surfaceHolder.lockCanvas();
        paint(c);
      } finally {
        if (c != null) {
          surfaceHolder.unlockCanvasAndPost(c);
        }
      }
    }
    

绘制方法将包含您所看到的内容。onDraw目前我在应用程序中遇到了相同的问题

在我的例子中,我试图从
[doInBackground()][1]
方法的
[AsyncTask][2]
调用
invalidate()


通过将
invalidate()
移动到
[onProgressUpdate()][3]
异步任务的方法,问题得以解决。也就是说,您不能从
AsyncTask
doInBackground()方法更新UI。Android文档中提到了它,但很容易忘记它。。。所以,别忘了检查一下。

我可能会迟到,但我相信这对你有用

我是与Kotlin一起做这件事的。您可以根据Java进行修改

将代码放入
runOnUIThread()

示例代码:

activity?.runOnUiThread { 
  // Your code goes here
}

希望这能有所帮助。

只是为了添加…除非您自己创建线程,否则所有代码都会在UI线程中执行。如果你在这个线程中睡眠或进行大量计算,那么用户界面的响应性就会降低,最终你会得到一个应用程序无响应(ANR)框。它是有效的。。。某种程度上。门现在是动画,但现在当我在屏幕上滚动时,图形会出现问题。我的游戏类中有一个手势监听器,当用户用手指滚动时,它会重新绘制屏幕。它允许你在地图上滚动。它过去画得很好。但是现在我画了一半的屏幕,另一半在校正自身之前半秒钟都没有更新。使用不同的视图类并不能解决这个“问题”。有必要了解永远不要在主线程中调用sleep,失效不会立即触发绘图,而是在下次UI线程有机会重新绘制时“记住”需要重新绘制的区域。您可能想看看相关的讨论,我已经阅读了此讨论,但我不明白我该怎么做才能让我的代码正常工作。我不知道如何使用“Handler”和“Message”。