1- [ TOC]
2-
31# 普通英雄和超级英雄
42
53## 需求
64
75
86我们需要开发一个游戏,游戏中有两种人物:普通英雄和超级英雄,他们具有下面的行为:
7+
98- 普通英雄只能移动
109- 超级英雄不仅能够移动,还能飞行
1110
1211我们使用下面的方法来渲染:
12+
1313- 使用Instance技术来一次性批量渲染所有的普通英雄
1414- 一个一个地渲染每个超级英雄
1515
@@ -49,18 +49,22 @@ World是游戏世界,由多个普通英雄和多个超级英雄组成。World
4949
5050首先,我们看下Client的代码;
5151然后,我们依次看下Client代码中前两个步骤的代码,它们包括:
52+
5253- 创建WorldState的代码
5354- 创建场景的代码
5455
5556然后,因为创建场景时操作了普通英雄和超级英雄,所以我们看下它们的代码,它们包括:
57+
5658- 普通英雄移动的代码
5759- 超级英雄移动和飞行的代码
5860
5961然后,我们依次看下Client代码中剩余的两个步骤的代码,它们包括:
62+
6063- 初始化的代码
6164- 主循环的代码
6265
6366然后,我们看下主循环的一帧中每个步骤的代码,它们包括:
67+
6468- 主循环中更新的代码
6569- 主循环中渲染的代码
6670
@@ -333,6 +337,7 @@ OneByOne渲染 SuperHero...
3333375.打印了WorldState
334338
335339我们看下打印的WorldState:
340+
336341- WorldState的normalHeroes中一共有两个普通英雄的数据,其中有一个普通英雄数据的position为[ 2,2,2] 而不是初始的[ 0,0,0] ,说明该普通英雄进行了移动操作;
337342- WorldState的superHeroes中一共有两个超级英雄的数据,其中有一个超级英雄数据的position为[ 6,6,6] ,说明该超级英雄进行了移动和飞行操作
338343
@@ -405,17 +410,21 @@ World是游戏世界,由多个GameObject组成。World负责管理所有的Gam
405410
406411首先,我们看下Client的代码;
407412然后,我们依次看下Client代码中前两个步骤的代码,它们包括:
413+
408414- 创建WorldState的代码
409415- 创建场景的代码
410416
411417然后,因为创建场景时操作了普通英雄和超级英雄,所以我们看下它们的代码,它们包括:
418+
412419- 移动的相关代码
413420- 飞行的相关代码
414421
415422然后,我们依次看下Client代码中剩余的两个步骤的代码,它们包括:
423+
416424- 初始化和主循环的代码
417425
418426然后,我们看下主循环的一帧中每个步骤的代码,它们包括:
427+
419428- 主循环中更新的代码
420429- 主循环中渲染的代码
421430
@@ -791,11 +800,13 @@ OneByOne渲染 SuperHero...
791800
792801通过打印的数据,可以看到运行的步骤与之前一样
793802不同之处在于:
803+
794804- 更新4个英雄现在变为更新4个positionComponent
795805- 打印的WorldState不一样
796806
797807
798808我们看下打印的WorldState:
809+
799810- WorldState的gameObjects包括了4个gameObject的数据,其中有一个gameObject数据的positionComponent的position为[ 2,2,2] ,说明它进行了移动操作;
800811- 有一个gameObject数据的positionComponent的position为[ 6,6,6] ,说明它进行了移动和飞行操作
801812
@@ -859,6 +870,7 @@ GameObject不再有数据和逻辑了,而只是一个全局唯一的id。组
859870
860871
861872- 增加System这一层,来实现行为的逻辑
873+
862874一个System实现一个行为,比如这一层中的MoveSystem、FlySystem分别实现了移动和飞行的行为逻辑
863875
864876
@@ -867,6 +879,7 @@ GameObject不再有数据和逻辑了,而只是一个全局唯一的id。组
867879
868880
869881值得注意的是:
882+
870883- GameObject和组件的数据被移到了Manager中,逻辑则被移到了Manager和System中。其中只操作自己数据的逻辑(如getPosition、setPosition)被移到了Manager中,其它逻辑(通常为行为逻辑,需要操作多种组件)被移到了System中
871884- 一种组件的Manager只对该种组件进行操作,而一个System可以对多种组件进行操作
872885
@@ -890,6 +903,7 @@ World是游戏世界,虽然仍然实现了初始化和主循环的逻辑,不
890903
891904我们看下System这一层:
892905有多个System,每个System实现一个行为逻辑。每个System的职责如下:
906+
893907- CreateStateSystem实现创建WorldState的逻辑,创建的WorldState包括了所有的Manager的state数据;
894908- UpdateSystem实现更新所有人物的position的逻辑,具体是更新所有PositionComponent的position;
895909- MoveSystem实现一个人物的移动的逻辑,具体是根据挂载到该人物gameObject上的一个positionComponent和一个velocityComponent,更新该positionComponent的position;
@@ -974,21 +988,26 @@ Manager层:
974988
975989首先,我们看下Client的代码;
976990然后,我们看下Client代码中第一步的代码:
991+
977992- 创建WorldState的代码
978993
979994然后,因为创建WorldState时会创建Data Oriented组件的Manager的state,其中的关健是创建各自的ArrayBuffer,所以我们看下创建它的代码
980995
981996然后,我们看下Client代码中第二步的代码:
997+
982998- 创建场景的代码
983999
9841000然后,因为创建场景时操作了普通英雄和超级英雄,所以我们看下它们的代码,它们包括:
1001+
9851002- 移动的相关代码
9861003- 飞行的相关代码
9871004
9881005然后,我们依次看下Client代码中剩余的两个步骤的代码,它们包括:
1006+
9891007- 初始化和主循环的代码
9901008
9911009然后,我们看下主循环的一帧中每个步骤的代码,它们包括:
1010+
9921011- 主循环中更新的代码
9931012- 主循环中渲染的代码
9941013
@@ -1047,6 +1066,7 @@ export type state = {
10471066` ` `
10481067
10491068这是PositionComponentManager的state的类型定义,它的字段解释如下:
1069+
10501070- buffer字段保存了一个ArrayBuffer,它用来保存所有的positionComponent的数据。目前每个positionComponent的数据只有position,它的类型是三个float
10511071- positions字段保存了ArrayBuffer的一个视图,通过它可以读写所有的positionComponent的position
10521072- maxIndex字段是ArrayBuffer上最大的索引值,用于在创建一个positionComponent时生成它的index值
@@ -1468,6 +1488,7 @@ OneByOne渲染 SuperHero...
14681488
14691489
14701490我们看下打印的WorldState:
1491+
14711492- WorldState的gameObjectManagetState的maxUID为4,说明创建了4个gameObject;
14721493- WorldState的positionComponentManagerState的maxIndex为4,说明创建了4个positionComponent;
14731494- WorldState的positionComponentManagerState的positions有3个连续的值是2、2、2,说明有一个positionComponent组件进行了移动操作;有另外3个连续的值是6、6、6,说明有另外一个positionComponent组件进行了移动操作和飞行操作;
@@ -1624,15 +1645,18 @@ Component+GameObject层:
16241645首先,我们看下属于用户的抽象代码
16251646然后,我们看下World的抽象代码
16261647然后,我们看下System层的抽象代码,它们包括:
1648+
16271649- CreateStateSystem的抽象代码
16281650- OtherSystem的抽象代码
16291651
16301652然后,我们看下Manager层的抽象代码,它们包括:
1653+
16311654- GameObjectManager的抽象代码
16321655- DataOrientedComponentManager的抽象代码
16331656- OtherComponentManager的抽象代码
16341657
16351658最后,我们看下Component+GameObject层的抽象代码,它们包括:
1659+
16361660- GameObject的抽象代码
16371661- DataOrientedComponent的抽象代码
16381662- OtherComponent的抽象代码
0 commit comments