0

我正在Scala中做一个模拟程序,我试图通过覆盖paintComponent来在JPanel中渲染模拟:

override def paintComponent(g: Graphics2D) = {
  g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  super.paintComponent(g)
  tx1 = g.getTransform()
  g.setColor(new Color(0,0,0))
   simulator.getVehicles foreach{vehc =>
    g.translate(vehc.getPos.x,vehc.getPos.y)
    g.draw(new Ellipse2D.Double(-Vehicle.rad, -Vehicle.rad, Vehicle.diam, Vehicle.diam))
    g.drawLine(0,0,(Vehicle.rad*vehc.getDir.x).toInt,(Vehicle.rad*vehc.getDir.y).toInt)
    g.setTransform(tx1)
  }
}

我让模拟本身在不同的线程上运行:

def run{
//logic loop
 time = System.currentTimeMillis();
 dt = 1000/60
while(loop)
{
  getVehicles.foreach{
  _.move
  }
  collider.solvecollisions()
  Thread.sleep(dt- (time - System.currentTimeMillis()))
  time = System.currentTimeMillis();
}}

GetVehicles 返回所有模拟车辆的 Buffer[Vehicle]。

我的问题是渲染中有抖动。我的意思是,有时某些车辆的渲染时间比其他车辆晚。我认为发生这种情况是因为模拟循环在渲染循环获取位置的同时更新了位置,并且存在一些重叠。即,当在时间步长 n 开始渲染时,一半的车辆被渲染,然后发生时间步长 n+1,其余的车辆进一步渲染一个时间步长。首先,我认为这是一个需要通过双缓冲来解决的问题,但由于paintComponent 已经这样做了,我认为情况并非如此。任何想法如何解决这一问题?我尝试简单地渲染 getVehicles.clone 但这并没有帮助,因为对车辆的引用仍然相同。

谢谢!

4

1 回答 1

1

看来您的车辆模型是可变的东西(_.move)。那么如果模拟和绘画在不同的线程中运行,那么在 Swing 中没有获得一致的世界观也就不足为奇了。

根据您的要求,我可以看到以下解决方案:

  • 在事件调度线程上运行模拟更新。优点:根本不需要更改您的代码。缺点:如果模拟繁重,可能会使 GUI 变得迟缓
  • 创建一个全局“世界”锁,您可以使用它synchronize。优点:对代码的改动很少。缺点:除非 GUI 更新速率较低,否则模拟和渲染都会相互阻塞。如果 GUI 更新只是模拟速率的一小部分,可能会很有用。
  • 采用不可变模型,然后您的模拟将在每一步中创建一个一致的更新世界。优点:渲染和模拟会自动保持一致。可能是最快的解决方案。缺点:你需要重写你的模拟。可能是最好的解决方案。
  • var将可变状态更改为STM参考单元。如果 GUI 速率与模拟速率相比较低,可能会很好地工作,因为这种“乐观”方法可能会在相对较少的回滚情况下工作。我不确定如何使用 Scala-STM 和渲染器进行只读访问。也许您需要一个完整的多版本 STM 来避免回滚。

概述不可变变体:

trait Vehicle {
  def move: Vehicle // return updated model
}

trait Collisions {
  def solve(in: Seq[Vehicle]): Seq[Vehicle] // return corrected models
}

trait World {
  def vehicles: Seq[Vehicle]
}

trait Simulator {
  protected def coll: Collisions

  // create updated world
  def run(prev: World): World = new World {
    val vehicles = coll.solve(prev.vehicles.map(_.move))
  }
}
于 2015-02-26T20:06:26.780 回答