Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Phaser framework 如何在ScalaJS中定义自定义JS对象_Phaser Framework_Scala.js - Fatal编程技术网

Phaser framework 如何在ScalaJS中定义自定义JS对象

Phaser framework 如何在ScalaJS中定义自定义JS对象,phaser-framework,scala.js,Phaser Framework,Scala.js,phaser游戏库有一个API,您可以在启动游戏场景时传递自定义对象。此数据对象可以是任何javascript对象,并且可以从场景中从中检索。我的问题是如何在phaser facades中以通用方式定义此对象,并在自己的代码中定义强类型版本 到目前为止,我只是在phaser API中将该对象引用为js.object,并在创建场景时将其转换为我自己的类型: @js.native trait ScenePlugin extends js.Object { def start(key: Scene

phaser游戏库有一个API,您可以在启动游戏场景时传递自定义对象。此数据对象可以是任何javascript对象,并且可以从场景中从中检索。我的问题是如何在phaser facades中以通用方式定义此对象,并在自己的代码中定义强类型版本

到目前为止,我只是在phaser API中将该对象引用为js.object,并在创建场景时将其转换为我自己的类型:

@js.native
trait ScenePlugin extends js.Object {
  def start(key: SceneKey, data: js.UndefOr[js.Object] = js.undefined): ScenePlugin
}

@js.annotation.ScalaJSDefined
class LevelConfig(
  val key: LevelKey,
  val loadingImage: Option[AssetKey] = None) extends js.Object

@ScalaJSDefined
class LoadScene extends Scene {
  private val loader = new SceneLoader(scene = this)
  private var levelConfig: LevelConfig = _

  override def preload(): Unit = {
    levelConfig = sys.settings.data.asInstanceOf[LevelConfig]
  }

  ...
}
这是可行的,但我不满意,因为我必须强制转换数据对象。传递到ScenePlugin.start的实际对象中的任何错误都将在运行时导致错误,我可能还只是使用了vanilla JS。另外,我的LevelConfig不能是一个case类,因为我得到了编译错误类和扩展js的对象。Any可能没有我不完全理解的case修饰符


以前有人处理过这种情况吗?你做了什么来避免这种情况?我猜这个问题源于正在使用的库,所以也许我需要在Phaser的Scene类周围创建某种包装来处理这个问题?我是ScalaJS的新手,我希望提高我的理解力,因此任何关于解决方案的解释都将受到赞赏和支持。非常感谢

我听从了贾斯汀·杜科尔的意见建议,修改了Phaser立面。我为SceneData对象定义了一个非本机特性,并更新了本机场景外观,使其具有两种类型,场景的子类必须覆盖这两种类型。Phaser场景是抽象的,旨在被覆盖,因此我认为这很有效:

class Scene(config: SceneConfig) extends js.Object {
  type Key <: SceneKey
  type Data <: SceneData

  def scene: ScenePlugin = js.native
  def data: Data = js.native

  def preload(): Unit = js.native
  def create(): Unit = js.native
  def update(time: Double, delta: Double): Unit = js.native
}

object Scene {
  trait SceneKey { def value: String }
  implicit def keyAsString(id: SceneKey): String = id.value

  trait SceneData extends js.Object
}

@js.native
trait ScenePlugin extends js.Object {
  def start[S <: Scene](id: String, data: js.UndefOr[S#Data] = js.undefined): ScenePlugin = js.native
}

我非常喜欢这样,因为现在不可能用另一个场景的配置类型启动一个场景。

问题:是否要以完全通用的方式定义外观?如果facade非常通用,允许使用各种类型,那么您的强类型代码除了强制转换之外没有太多选择。但请记住,您的facade可能比底层JS库更严格,前提是它充分描述了您将来回传递的所有数据。我并不真正关心facade的类型,只要它不是硬编码到特定对象。每个游戏都有多个场景对象,这些场景对象可能有不同的数据对象传递给它们。在这种情况下,演员可能是一个必要的恶魔。这其实并不罕见——Scala.js是一个例外,通常的规则是您应该始终避免安装。当您处于强类型Scala和弱类型JavaScript之间的边界时,这通常是必要的。我通常将强制转换封装在API代码中,然后从应用程序代码中调用这些API。
class LoadScene extends Scene(LoadScene.Config) {
  override type Key = LoadId.type
  override type Data = GameAssets

  override def preload(): Unit = {
    createLoadBar()
    loadAssets(data)
  }

  private def createLoadBar(): Unit = { ... }
  private def loadAssets(config: GameAssets): Unit = { ... }

  override def create(): Unit = {
    scene.start[GameScene](GameId)
  }
}

object LoadScene {
  case object LoadId extends SceneKey { val value = "loading" }
  val Config: SceneConfig = ...
}