LibGDX架构设计指南。

4
我作为一名安卓客户端-服务器应用程序开发者,需要处理许多架构设计模式和指南以供选择和遵循。
其中最流行的包括:
- MVP或MVVM - Clean Architecture - Repository Pattern - 依赖注入技术等等...
由于模式的严格要求,开发人员必须承认模式本身仅是建议,而并非Android SDK所必需的。
同样适用于LibGDX。该库没有提供严格的规则或要求,因此开发人员可以自由决定如何编写游戏。
那么问题来了:
对于LibGDX游戏开发人员,是否有一些推荐、设计指南甚至标准可供遵循?我应该如何编写代码(使用LibGDX),以便其他开发人员可以轻松理解?
2个回答

1
从我的经验来看,没有一种标准是所有人都在遵循的。libGDX开发人员来自不同的背景。有些人是后端开发人员,在日常生活中工作,有些人只是业余爱好者,学习他们的第一个开发技能。
我看到很多libGDX开源项目使用典型的静态SomeManager.getInstance()调用,而我更喜欢通过引用传递(作为后端开发人员,你会知道其中的优点-可测试性等)。
即使是libGDX后端本身也没有遵循单一的方法。有些部分通过反射获取管理器的引用(这并不好,因为你必须从混淆中排除这样的类),有些则使用静态getInstances()。
如果你也涉及HTML5,你也必须尊重一些基于GWT的限制,所以有时你会被迫采取一种你在开发Spring Boot应用程序时永远不会采取的方式。

1

现在过去了3年,我可以自己回答这个问题了。

我发现使用ECS(实体-组件-系统)是创建游戏的最佳方法。

采用这种方法,您将拥有3个不同的目的对象。正如名称所示,它们是:

  • Entity - 只是一个通用对象,仅包含一组component对象和通常的ID
  • Component - 是一组数据,没有逻辑,只是简单的POJO。它包含的数据将定义包含该组件的Entity的行为。
  • System - 这是您放置逻辑的地方。每个系统应仅在包含非常特定的components集的entity上进行处理。
  • Engine - 是场景的表示,所有entities都生活在其中,并由systems处理。

实现这种方法最简单的方式是使用Ashley库。它是ECS的轻量级实现。虽然我的经验表明,这在实际游戏玩法中效果最佳。如果你想要非常具体的动画(甚至是游戏对象的动画),那么请使用Scene2d

{{link2: Scene2d} }代表了更为熟悉(对于绝大多数开发者)的方法。它是一组UI元素的图形结构,这些元素按层次结构放置。有非常有用的Action可以用来实现你的动画。它也适用于你想在游戏中显示的任何UI。

总之,我总结出,你应该每个屏幕至少拥有几个类,以实现分工明确。

  • Screen - 我将其视为运行代码的一个分支。它包含一个 Engine(如果我们需要 ECS)和一个 Stage(如果我们需要 UI)。处理所有游戏事件、用户输入和路由。
  • Engine - ecs 容器,知道如何管理其系统、实体和组件。
  • Stage - UI 容器,知道哪些 UI 元素应该存在,它们应该如何展示和表现。

Kotlin 中的简单示例(注意,在我的真实项目中,我使用 koin DI 将所有内容绑定在一起):

class MyGameScreen : Screen, MyGameEngine.Callback, MyGameStage.Callback {

    val engine = MyGameEngine(callback = this)
    val stage = MyGameStage(callback = this)

    override fun create() {
        engine.create()
        stage.create()
    }

    override fun render(delta: Float) {
        enigne.update(delta)
        stage.act(delta)
        stage.draw()
    }

    override fun dispose() {
        enigne.dispose()
        stage.dispose()
    }

    override fun buttonPress() {
        //handle button press
    }

    override fun onGameEvent(event: MyGameEngine.Event) {
        //handle some game event
    }

}

class MyGameEngine(
    private val callback: Callback
) : com.badlogic.ashley.core.PooledEngine() {

    fun create() {
        // create and add all your systems and entities
    }

    sealed class Event {
        // ...
    }

    interface Callback {
        fun onGameEvent(event: Event)
    }

}

class MyGameStage(
    private val callback: Callback
) : com.badlogic.gdx.scenes.scene2d.Stage() {

    val button1 = TextButton(...).apply {
        addClickListener { callback.buttonPress() }
    }
    
    val label1 = Label(...)

    // and so on

    fun create() {
        val root = Table().apply {
            // add all your actors to the root table
        }

        val rootContainer = Container(root).apply {
            setFillParent(true)
            fill()
            top()
        }

        addActor(rootContainer)
    }

    fun startSomeAnimation() {
        val action = Actions.sequence(
            // your animation
        )

        addAction(action)
    }

    interface Callback {
        fun buttonPress()
    }

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接