Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

开发计划 #1

Open
9 of 44 tasks
woct0rdho opened this issue Feb 10, 2024 · 5 comments
Open
9 of 44 tasks

开发计划 #1

woct0rdho opened this issue Feb 10, 2024 · 5 comments

Comments

@woct0rdho
Copy link
Contributor

woct0rdho commented Feb 10, 2024

框架使用语言:C#

演出脚本使用语言:GDScript

NovaScript(流程图定义+剧情文本+演出脚本)格式:就用原来的,但是把演出脚本的Lua替换成GDScript

  • NovaScript parser
    • 可以先不parse演出脚本
    • 由于Godot不能分割asm,第三方插件可能无法使用?
    • 演出脚本使用gdscript
    • 所有C#类需要继承GodotObject才能被gdscript使用(直接继承RefCounted即可)
    • 如果是struct之类的东西需要从Godot.Collections.Dictionary转换
  • 基本的GameState
    • 标题界面+开始游戏按钮
    • 对话框
    • GameState
    • Godot不需要Unity的DontDestroyOnLoad,所以不需要写一个NovaCreator然后用它加载NovaController
      • NovaController直接改成单独的Node即可
      • 不考虑Scene切换的问题
    • GameState之类的东西可以不做成Godot的node,而是直接让NovaController拿着引用
      • 所有的Singleton都改成从NovaController初始化
      • 如果某个Singleton需要被演出脚本使用,需要继承RefCounted
  • 选项
  • 演出脚本
    • 可以先用print来测试
  • AssetLoader
  • 图片
    • 从做第一个前端组件开始,考虑把前端(view)和后端(model)分离,演出脚本操作的是model,存档存的也是model,这样跳转和快进等功能会更方便
  • 立绘合成系统
    • Godot支持给不是power of two的图片加mipmap吗,支持的话很多东西就好办了
    • qiankanglai在群里说过,如果立绘的图层先画前面再画后面,并且只有最后一层允许有透明,可以减少overdraw,但是不知道会不会影响mipmap https://github.com/qiankanglai/Nova/tree/sprite_comp
  • 头像
  • BGM
    • Godot可以设置音乐的loop begin point,我们不用自己写了
  • 音效
  • 语音
  • 动画系统
    • 最好不要自己写,看看能用什么包
  • 对话框的文字动画
  • CameraController
  • VFX
    • 如果能用Godot现有的功能实现我们需要的shader variant和metadata,就不要自己写
    • 转换shader名字的格式现在应该不用了
  • 转场
  • 加载场景(相当于PrefabLoader
  • TimelineController
  • 视频
  • 变量
  • 脚本热加载

一个小目标:【下一部长篇作品】开始做演出之前,把演出系统基本做完,然后慢慢做UI


  • 预加载系统
  • 随意缩放窗口
  • 对话框的完整功能
    • 隐藏对话框
    • 用脚本控制对话框位置、皮肤
    • 对话结束图标
    • 对话框动画?
    • 多个对话框的支持等做完机械恋心应该就知道怎么做了
  • 鼠标菜单
    • 按照机械恋心的13个按钮来做
  • 警告框
    • 我感觉目前的Alert系统太over engineer了,可以直接把Alert和Notification拆成两个类,我们不会再加更多种类的Alert了(除非先重写窗口管理系统。。)
    • 实践证明警告框的标题是不需要的,可以删了
  • 通知框
    • Nova里用了VerticalLayoutGroup来控制通知框的竖直位置,但是它也会控制通知框的水平位置,可能会跟通知框水平移动的动画冲突,可以按机械恋心来做
  • 存档系统
    • 考虑重写CheckpointSerializer,把全局存档分成三个文件,相当于不要自己搞链表,交给文件系统来搞
  • 存档界面
    • 先按机械恋心来做,对触摸屏和手柄的支持比青箱好
  • 文本回顾界面
    • 我们把LogController的名字改成BacklogViewController吧,因为log这个词在其他地方用得太多了
  • ViewManager

存档界面和文本回跳做完之后,调试演出会更方便


  • UI动画
  • 设置界面
    • 考虑手柄支持,可以把所有设置排列得比较整齐,像很多主机游戏一样
  • 快捷键系统
  • 图片鉴赏
    • 机械恋心做完之后,我们可能会把图片鉴赏改成跳转到游戏里特殊的node
  • 音乐鉴赏
  • 手柄支持
  • 立绘裁剪工具
  • 自动语音
  • 小游戏
    • 有需求再做,没需求的话先把GameState里的那些东西照搬过来
  • I18n
    • 有需求再做,【下一部长篇作品】估计没有需求
@soryu-ryouji
Copy link
Collaborator

目前优先迁移的组件:

  1. Checkpoint
  2. GameState
  3. NovaScript
  4. NovaAnimation
  5. DialogueBox

新版本中希望解决的问题:

  1. LifeCycle,Nova所有的Singleton有非常多初始化的方式,且顺序非常不明确,最好是统一成NovaController这样子
  2. 去掉CheckpointBlock,把global save拆成若干个文件
  3. 尽可能前后端分离,因为并不是每个dialogue都存Checkpoint的,load的时候会重放script,GameState的状态最好和前端组件无关,并且大致上保证script对于相同的状态效果是一样的(也就是pure的)

@gyf1214
Copy link
Contributor

gyf1214 commented Mar 12, 2024

考虑NovaScript直接使用gdscript

@gyf1214
Copy link
Contributor

gyf1214 commented Mar 14, 2024

命名规范:https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/identifier-names
省流:

  • PascalCase: namespace, class, public/protected field, function
  • camelCase: local variable
  • _camelCase: private field
  • s_camelCase: private static field
  • interface starts with I

@woct0rdho woct0rdho pinned this issue Mar 18, 2024
@gyf1214
Copy link
Contributor

gyf1214 commented Mar 20, 2024

如何编译GDScript:

  • 每个GDScript都是一个类,现在的方案是将每个代码块编译成一个类,然后通过GDScript.New创建对象并运行
  • 所有Lazy代码块继承LazyBlock
  • 所有Eager代码块继承EagerBlock
  • 所有跳转Condition继承ConditionBlock
  • LazyBlockEagerBlock继承自RuntimeBlock
  • 所有Block继承自BaseBlock
  • 所有代码块都会包装成__eval方法,执行代码块的时候会调用run方法,可以在run方法中添加hook函数
  • 将所有演出脚本需要的API方法实现为基类的成员方法,就可以直接在代码块里调用

GDScript和C#的交互:

  • GDScript类无法和C#类互相沟通
  • 所有GDScript类继承自GodotObject(绝大部分直接继承RefCounted),使用Call方法动态调用GDScript函数
  • 除了少量builtin类型,C#对象必须继承GodotObject才能在GDScript被使用
  • C#静态类无法在GDScript里使用,也不能直接调用静态方法,但是似乎可以通过类的对象调用静态方法
    • 因此最好使用Singleton模式而不是静态类
  • C#类如果继承自GodotObject,会自动生成代码使得GDScript可以动态调用成员变量、属性和方法
    • 成员、函数参数和返回值必须都是GDScript兼容的类型(继承GodotObject
    • 不能存在泛型
    • 如果不满足上述条件,对应的成员无法在GDScript中使用
    • 因此,所有需要被演出脚本访问的类都要继承RefCounted

@gyf1214 gyf1214 mentioned this issue Mar 20, 2024
@gyf1214
Copy link
Contributor

gyf1214 commented Mar 20, 2024

如何bind C#对象到gdscript

  • gdscript不支持动态添加属性,但是Dictionary有一个语法糖:a.x等同于a["x"]
  • 需要bind的对象调用NovaController下的ObjectManager.BindObject
    • 必须在_Ready之前bind
  • ObjectManager.Objects返回所有对象的Dictionary
  • ObjectManager.Constants返回所有常量的Dictionary
    • 常量必须在构造函数时初始化
  • 在gdscript中添加了一些shortcut property:
    • nova等价于NovaController.Instance
    • o等价于nova.ObjectManager.Objects
    • c等价于nova.ObjectManager.Constants
  • 对于show,set_box等方法,既可以传入对象,也可以传入名字:
    • show(o.fg, "rain_back")
    • show("fg", "rain_back")

@gyf1214 gyf1214 mentioned this issue Mar 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants