Braid时间控制引擎的初步设计讨论

  • 偏微分
    讨论前提:
    初步设计而已,自然不会涉及到代码。懂技术的可以谈得深一点,不懂技术的,谈谈自己的粗略想法即可,比如我就不懂技术。

    讨论目标:
    初步设计一个实现时间控制的引擎框架,使Braid各个世界的特点都能在这个框架的基础之上做小幅度调整即可兼容。

    举例
    A君提议:“把各个物体的运动过程录下来,按shift的时候倒放不就可以了。。。”
    B君:“那绿色的物体怎么办?”
    C君:“绿色物件不参与倒放不就可以了”
    D君:“世界3的那种时间特性怎么实现?”
    E君:“倒走的时候触发主角外其他物件的倒放不就可以了”。
    F君:“倒放的物件是否参与碰撞检测?”
    G君:“声效,特效的倒放如何同步?”
    H君:“那个,A君提到的“运动过程录下来”,具体该记录哪些参数?”
    I君:“坐标,矢量速度,动画帧,状态(存活,死亡,消失,打开,关闭...)”
    J君:“日,那么多参数,根据指环的效果看,背景上的那些雪花貌似都是独立物件,估计Braid跑一个小时,内存就完蛋了”

    [本帖最后由 偏微分 于 2009-4-15 20:27 编辑]
  • e
    eternia
    世界3中左右矢量的值和封闭时间段A-B之间的每一个值相对应

    非常神奇,让我看到了满屏的哲理……
  • g
    galon
    只有主角和兔子的状态是需要“录”的,兔子有ai,那啥馒头敌人都是走固定路线固定触发时间的,需要记录的也就死亡时间,其他道具记录触发时间就行了
    所有物体运动都跟时间轴连在一起
  • 精钢魔像
    不知道Braid是什么所以不知道你们在讲什么

    但是,

    J君:“日,那么多参数,根据指环的效果看,背景上的那些雪花貌似都是独立物件,估计Braid跑一个小时,内存就完蛋了”

    这是错的,内存有分配就有回收,没有跑x小时就完蛋的说法
  • c
    cxasuka
    先把对象的各种属性都分析出来,然后按属性分类,再去搞别的。背景那种东西如果按照预定的算法来做的话,并不需要保存什么属性,直接从一个时间点倒着计算就可以了。
  • N
    Ny
    我觉得是跟war3的replay记录的数据类似
    只记录玩家的操作, 其他的比如碰撞都是程序运算出来的
  • l
    lionheart007
    这游戏的灵感是jojo奇妙冒险里来的吧
  • s
    saviolazy
    时间反复倒流,其中还能更改事实,有点像吉良吉影的替身,但限制要小得多。
  • S
    StonH
    可以尝试把物件大致分成两类,一种能与主角交互(各种可动或者破坏物体)另外一种不能(比方说雪花)。对于不能交互物件只要可以提供一个反向的引擎算法并且记录构造和析构时的状态并且对应到时间轴上应该就可以完成时间逆向的目的。

    而对于可交互物件可以尝试记录交互方式和交互的状况(比方说坐标和受力方向),在时间逆向的时候可以要求引擎完成正常的计算然后反向播放就可以。这样减少了空间复杂度但是大大增加了时间复杂度。在物件会破碎的情况下所需计算量会很大。
    或者干脆记录可交互物件所有运动状态然后反向播放,这样在实现上可能会比较方便但是内存代价太大并且会限制全局的物件总数。而且在操作上会相当消耗资源,释放\"过去的\"然后记录\"新的过去\"

    稍微想了一下,有问题请拍
  • S
    StonH
    而且如果记录状态的话最好的方法就是用栈操作,但是栈本身特性决定了记录的信息不能太大,可以用限制时间回溯长度来解决,就像波斯猴子那样。

    真实世界的信息量是很恐怖的。

    虽说咱们没有办法保证这个世界不是缸中之脑。

    [本帖最后由 StonH 于 2009-4-15 20:02 编辑]
  • 偏微分
    感觉记录状态是下下策,优点是容易实现,缺点是耗费资源太大。最好是能实现“逆动作”。比如photoshop里的“撤销”功能,应该是做之前操作的“逆操作”,而不是为每一个操作都保留一个图像副本。当然,实际情况可能是某些操作本身没有逆操作,或者很难实现。这时候还不如存一个副本来得简单。
    这样,倒放过程就不是单纯的“播片”,然是调用物体的逆动作而已。当然,一些关键点的参数还是少不了的。

    [本帖最后由 偏微分 于 2009-4-15 20:26 编辑]
  • S
    StonH
    从程序的角度来说记录状态确实不是好办法,但是在真实环境中完成从非特定初始状态到非特定结束状态可能的方法有无数种,只能记录\"使它改变状态的力的状态\"。这样在引擎在保证数学上结果唯一的状态下才能完成时间逆向。而且物件没改变一次状态就要记录一次起始和完结状态。比方说一个物体受到外力发生了破碎,碎片之间的碰撞,碎片与外界的影响,直到达到与某个参照系相对静止的情况下结束。这样在回溯的时候引擎需要完成所有时间轴正方向计算之后把计算结果倒过来播放才能完成时间在感觉上的回溯。如果碎片数量比较大的话计算量可想而知,而且在完成所有计算之前用户必须等待,而且弄不好还要上自旋锁。太不合算了。

    相对的纯粹的状态记录在这方面就要好很多。

    熵减可没那么简单。

    还有比较复杂的诸如流体和火焰种种。。。
  • S
    StonH
    像war3的replay大概只记录用户的操作,而用户操作的种类是很有限的(选中,前往,攻击,技能),这样整体的信息量就不会很大,而且war3引擎的真实环境量也没有很多(重力等等)

    而且据我所知war3的replay同样没有倒放。。。
  • g
    galon
    LS 够蛋疼的

    2D游戏状态数据量太小了,比起3d来说基本不是一个级别的,一个3d骨骼动作数据就比你大多了,即使是3D RTS其本质也不过是个2D棋盘游戏而已,记录数据量也很少
  • S
    StonH
    我觉得我也是够蛋疼的。。

    但我真的很想知道matrix的引擎架构啊啊啊!
  • y
    yakumo
    LSS是不是没玩braid?波斯猴子的确是堆栈,braid更有趣,简单介绍下

    braid关于取得隐藏星星部分听闻需要在同一关卡等待几个小时,虽然我没有试过,不过我想这些应该都是可以回放的。

    排除背景和关卡一些规律运动的物体外,NPC大致分设定为碰撞墙壁后折向的简单变量式和此外会主动靠近主角并且近身后超主角方向跳跃的简单AI型。同屏NPC还未见过超过10个。

    首先我想记录画面是不可能的,因为那样即时不使用大量内存也要使用大量硬盘空间作暂存——而我没有察觉到有。

    我想可能是,和时间产生互动的NPC使用类似于二次函数的方法:X为时间,按0.x秒为一循环递增;Y为另一个二次函数——A与B分别记录此变量在屏幕XY轴上的坐标。然后依次记录。当读取时间变量X1时,进入子程序,调用2次函数在屏幕上反映Y值的坐标(A,B),同时将最大值Xn至X1部分清零,之后重新进入主程序循环赋值。

    也就是说,也是类似于魔兽那样只记录操作,然后调用程序读值演算反映于屏幕上那样。不过更简单直接。

    我想这样的话需要记录的数据就会小很多,用内存+硬盘暂存就可以完成。当然,这是我个人的理解。

    不是做游戏的,讲的粗糙,欢迎拍砖。
  • y
    yakumo
    被插楼了,回stonh同学
  • 颜小山
    虽然不专业,但是一直卡着的人帮忙顶楼
  • 熊猫阿黑
    如果War3只记录人的操作而其他还是靠运算的话,单位的攻击是有浮动值的,这个问题怎么解决

    或者单独为此再列个数据,某单位在某时刻的攻击力是多少
  • g
    galon
    记录啥时候挂点不就是了
  • 自由质子
    消耗的随机数列也被记录下来了的

    我也觉得war3的记录方式靠谱
  • 自由质子
    不会记录下什么时候挂点

    整个录像基本等于重演一遍玩家的游戏过程 完全重新计算 所以就像前面某位说的一样 没有倒放 因为后面发生的事件其实还没有发生
  • W
    Wiksy
    只要记录一开始的随机种子就可以了
  • S
    StonH
    确实没玩,最近好忙。。。
    求。。。求下载。。。
    貌似没有破损物件?那只处理敌人就可以了。


    我同意,不过我的意思是说环境的respawn才是令人觉得头疼的地方。当然Braid我没玩,下面是我想象中的回溯引擎会碰到的问题,跟Braid无关,只是讨论,别打。。
    假设现在有敌人,周围有一些可以被打碎的箱子,然后敌人在攻击的时候打碎了一些箱子,打歪了一些箱子,然后杀死主角,这个时候回溯,那么引擎就需要完美的把箱子的碎片重新按照原来的路线飞回原处并且粘成\\\"原来\\\"的箱子,同时处理敌人的动作和主角。这样才能算回溯。如果说主角被杀,回溯,然后回溯完成主角发现旁边的箱子不在了。。
    所以说如果只记录环境的关键信息在长时间回溯上会碰到问题。比方说玩家突然发现一个小时之前那个场景忘了做某件事情,回溯。这个时候引擎需要根据记录运算出这一个小时所有发生过改动的地方,然后把结果临时存起来,再倒放。这样的代价就很大了。当然,如果只有敌人没有互动环境的话就没有这许多问题。


    攻击确实是有浮动值,但造成的伤害是固定的即成事实,这样录像系统只关心对象在某个时间,受到多少伤害,然后判断是否call void Die(const object*)。录像系统并不关心这个伤害是从何而来,是何种伤害。只要记录下所有的玩家操作(关键信息)和物体状态(受到的伤害 etc)。还是那个意思,回溯系统只需要记录已经发生的事实,这里面不会有不确定性存在。问题只是如何记录而已。只要游戏引擎和图像引擎保证在输入唯一的情况下输出唯一,所有的物件状态应该是100%还原的,在replay的时候,自然能匹配上上。
    不过在寻路结果上,可能会做一些存储。当然,只是我猜。。。


    随机数种子目前的实现大多是开机经过的毫秒数。但是随机数表的查询结果并不唯一,而且貌似并没有那个必要。总不能说我这个英雄是不是在replay里面被杀死取决于主板上的那个晶振工作是不是正常吧lol

    ps:自然界里面真的有随机事件么?啊,好难。。

    [本帖最后由 StonH 于 2009-4-17 20:02 编辑]