百木园-与人分享,
就是让自己快乐。

3D网页小实验-基于多线程和精灵动画实现RTS式单位行为

一、实验目的:

1、在上一篇的“RTS式单位控制”的基础上添加逻辑线程,为每个单位实现ai计算;

2、用精灵动画为单位的行为显示对应的动作效果。

二、运行效果:

1、场景中的单位分为红蓝两方,单位在发现敌对单位后向敌人移动:

2、进入攻击范围后对敌对单位发起攻击:

 

注意,单位在“移动”、“攻击”、“受伤”、“死亡”时分别播放不同的动画。

3、切换为RTS式控制后,可以选择单位并发布“移动攻击”命令:

有一些单位已经与敌人接触,优先执行攻击动作。

三、程序结构:

1、工程目录:

 

 外层ASSETS目录保存了场景的地面贴图、天空盒、地形资源,内层ASSETS目录下是单位的精灵动画资源。(实际的github仓库里还有上篇文章的代码)

2、线程结构:

 

 主线程中的TESTRTS.html是程序入口,负责初始化WebGL场景和与逻辑线程通信,babylon50.min.js是Babylon.js引擎库,newland.js是一个Web3D工具库,One.js是单位渲染代码,VTools.js是向量计算代码,ControlRTS3.js是rts控制代码,FrameGround2.js是地形生成代码,recast.js是群组导航库。主线程负责dom管理、WebGL场景的渲染、单位的群组寻路、单位的动画计算。

逻辑线程中的worker.js负责初始化逻辑环境、维持逻辑循环和与主线程通信,OneThink.js负责单位ai计算。逻辑线程和主线程间使用postMessage进行通信。

四、主线程初始化:

在之前的文章中介绍过的内容不再赘述,这里只讨论新增的部分,可在https://github.com/ljzc002/ControlRTS下载代码,国内访问github的一种方法见附录一。

1、生成单位的精灵动画图片:

场景中使用的精灵动画图片如下:

这是一张透明背景的PNG图片,图中每个128*128的像素小块对应精灵动画的一帧,这种图片一般由美工使用专业工具绘制,但这里为演示方便用代码生成:

1 <!DOCTYPE html>
2 <html lang=\"en\">
3 <head>
4 <meta charset=\"UTF-8\">
5 <title>建立用于精灵动画的方块图列</title>
6 </head>
7 <body>
8 <div id=\"div_allbase\" ><!--style=\"border:1px solid #888888;width: 1282px;height: 386px\"-->
9 <canvas id=\"renderCanvas\" width=\"1280\" height=\"384\" style=\"width: 1280px;height: 384px;border:1px solid #888888;padding: 0px;margin: 0px\"></canvas>
10 </div>
11 </body>
12 <script>
13 var canvas=document.getElementById(\"renderCanvas\");
14 var ctx=canvas.getContext(\"2d\");
15 var count_draw=0;
16 var oX=0;
17 var oY=0;
18 ctx.fillStyle=\"rgba(255,255,255,0)\";//透明背景
19 ctx.strokeStyle=\"#222222\";
20 ctx.fillRect(0,0,1280,384);
21 //ctx.beginPath();
22   //相对于每个小块的中心绘制
23 ctx.oArc=function(x,y,r,sAngle,eAngle,counterclockwise)
24 {
25 ctx.arc(x+oX,y+oY,r,sAngle,eAngle,counterclockwise)
26 }
27 ctx.oMoveTo=function(x,y)
28 {
29 ctx.moveTo(x+oX,y+oY);
30 }
31 ctx.oLineTo=function(x,y)
32 {
33 ctx.lineTo(x+oX,y+oY);
34 }
35 ctx.oRect=function(x,y,width,height)
36 {
37 ctx.rect(x+oX,y+oY,width,height);
38 }
39
40
41 //根据头的位置和四肢角度绘制一个二维的小人儿,角度采用顺时针,头位置,头左右转动,头上下俯仰,身体倾斜,左上臂角度,,,,左大腿角度
42 function DrawaMan(phx,phy,ahy,ahz,ab,alh1,alh2,arh1,arh2,alf1,alf2,arf1,arf2)
43 {//根据参数画小人儿的方法
44 ctx.beginPath();
45 oX=count_draw%10*128;
46 oY=Math.floor(count_draw/10)*128;
47
48 var obj_aman={ph:{x:phx,y:phy}};
49 var rh=5;//头半径
50 var lb=20;//身长
51 var lh1=8;//
52 var lh2=8;//
53 var lf1=10;//
54 var lf2=10;//
55 ctx.oArc(phx,phy,rh,0,Math.PI*2);
56 ctx.stroke();
57 //暂时不画眼睛,这样ahy,ahz暂时没有直接作用
58 var x1=phx,y1=phy+rh;
59 var x2,y2,x3,y3;
60 ctx.oMoveTo(x1,y1);
61 obj_aman.pb1={x:x1,y:y1};
62 x2=x1-lb*Math.sin(ab);
63 y2=y1+lb*Math.cos(ab);
64 ctx.oLineTo(x2,y2);
65 obj_aman.pb2={x:x2,y:y2};
66 ctx.stroke();
67
68 ctx.oMoveTo(x1,y1);
69 x2=x1-lh1*Math.sin(ab+alh1);
70 y2=y1+lh1*Math.cos(ab+alh1);
71 ctx.oLineTo(x2,y2);
72 obj_aman.plh1={x:x2,y:y2};
73 ctx.stroke();
74
75 ctx.oMoveTo(x2,y2);
76 x3=x2-lh2*Math.sin(ab+alh1+alh2);
77 y3=y2+lh2*Math.cos(ab+alh1+alh2);
78 ctx.oLineTo(x3,y3);
79 obj_aman.plh2={x:x3,y:y3};
80 ctx.stroke();
81
82 ctx.oMoveTo(x1,y1);
83 x2=x1-lh1*Math.sin(ab+arh1);
84 y2=y1+lh1*Math.cos(ab+arh1);
85 ctx.oLineTo(x2,y2);
86 obj_aman.prh1={x:x2,y:y2};
87 ctx.stroke();
88
89 ctx.oMoveTo(x2,y2);
90 x3=x2-lh2*Math.sin(ab+arh1+arh2);
91 y3=y2+lh2*Math.cos(ab+arh1+arh2);
92 ctx.oLineTo(x3,y3);
93 obj_aman.prh2={x:x3,y:y3};
94 ctx.stroke();
95
96 //开始画腿
97 x1=obj_aman.pb2.x;
98 y1=obj_aman.pb2.y;
99
100 ctx.oMoveTo(x1,y1);
101 x2=x1-lf1*Math.sin(ab+alf1);
102 y2=y1+lf1*Math.cos(ab+alf1);
103 ctx.oLineTo(x2,y2);
104 obj_aman.plf1={x:x2,y:y2};
105 ctx.stroke();
106
107 ctx.oMoveTo(x2,y2);
108 x3=x2-lf2*Math.sin(ab+alf1+alf2);
109 y3=y2+lf2*Math.cos(ab+alf1+alf2);
110 ctx.oLineTo(x3,y3);
111 obj_aman.plf2={x:x3,y:y3};
112 ctx.stroke();
113
114 ctx.oMoveTo(x1,y1);
115 x2=x1-lf1*Math.sin(ab+arf1);
116 y2=y1+lf1*Math.cos(ab+arf1);
117 ctx.oLineTo(x2,y2);
118 obj_aman.prf1={x:x2,y:y2};
119 ctx.stroke();
120
121 ctx.oMoveTo(x2,y2);
122 x3=x2-lf2*Math.sin(ab+arf1+arf2);
123 y3=y2+lf2*Math.cos(ab+arf1+arf2);
124 ctx.oLineTo(x3,y3);
125 obj_aman.prf2={x:x3,y:y3};
126 ctx.stroke();
127
128 count_draw++;
129 //,ab,alh1,alh2,arh1,arh2,alf1,alf2,arf1,arf2
130 obj_aman.ab=ab;
131 obj_aman.alh1=alh1;
132 obj_aman.alh2=alh2;
133 obj_aman.arh1=arh1;
134 obj_aman.arh2=arh2;
135 obj_aman.alf1=alf1;
136 obj_aman.alf2=alf2;
137 obj_aman.arf1=arf1;
138 obj_aman.arf2=arf2;
139 return obj_aman;
140
141 }
142 //第一只手(右手)的位置,第二只手的位置(可能为空),第一只手距矛头的距离,长矛在世界坐标系中距y轴负方向逆时针弧度
143 function DrawaSpear(ph1,ph2,d,a)//根据参数画长矛的方法
144 {
145 ctx.beginPath();
146 var obj_spear={}
147 var ls=60;
148 var ss=5;//矛头的每边长度
149 var as=Math.PI/6
150
151 if(ph2)//那么就不需要a
152 {
153 if((ph1.y-ph2.y)>=0)
154 {
155 a=Math.atan((ph1.x-ph2.x)/(ph1.y-ph2.y));
156 }
157 else
158 {
159 a=Math.PI+Math.atan((ph1.x-ph2.x)/(ph1.y-ph2.y));
160 }
161
162 }
163 var x1=ph1.x+d*Math.sin(a);
164 var y1=ph1.y+d*Math.cos(a);
165 var x2=ph1.x-(ls-d)*Math.sin(a);
166 var y2=ph1.y-(ls-d)*Math.cos(a);
167 ctx.oMoveTo(x1,y1);
168 ctx.oLineTo(x2,y2);
169 ctx.stroke();
170 obj_spear.pst={x:x2,y:y2};
171
172 var lsh=ss*Math.cos(as)*2
173 var x3=x1+lsh*Math.sin(a);
174 var y3=y1+lsh*Math.cos(a);
175 obj_spear.psh={x:x3,y:y3};
176
177 ctx.oMoveTo(x1,y1);
178 x2=x1+ss*Math.sin(a+as);
179 y2=y1+ss*Math.cos(a+as);
180 ctx.oLineTo(x2,y2);
181 ctx.oLineTo(x3,y3);
182 ctx.stroke();
183
184 ctx.oMoveTo(x1,y1);
185 x2=x1+ss*Math.sin(a-as);
186 y2=y1+ss*Math.cos(a-as);
187 ctx.oLineTo(x2,y2);
188 ctx.oLineTo(x3,y3);
189 ctx.stroke();
190
191 return obj_spear
192 }
193   //初始
194 var grid_original=DrawaMan(64,25,0,0,0,Math.PI/6,-Math.PI/6,-Math.PI/6,Math.PI/6,Math.PI/6,-Math.PI/6,-Math.PI/6,Math.PI/6)
195 var spear_original=DrawaSpear(grid_original.prh2,grid_original.plh2,20);
196
197 var grid=DrawaMan(64,28,0,0,0,0.5235987755982988,-1.0471975511965976,-0.6981317007977318,0.17453292519943292,0.6981317007977318,-0.34906585039886584,-0.6981317007977318,1.0471975511965976)
198 var spear=DrawaSpear(grid.prh2,grid.plh2,26);
199
200 var grid=DrawaMan(64,31,0,0,0,0.5235987755982988,-1.5707963267948966,-0.8726646259971647,-0.17453292519943298,0.8726646259971647,-0.17453292519943292,-0.8726646259971647,1.5707963267948966)
201 var spear=DrawaSpear(grid.prh2,grid.plh2,33);
202
203 //先保持头部高度不变,看脚高了多少,然后再反过来调整头部高度(攻击)
204 var grid_3=DrawaMan(64,35,0,0,0,Math.PI/6,-Math.PI*2/3,-Math.PI/3,-Math.PI/6,Math.PI/3,0,-Math.PI/3,Math.PI*2/3)
205 var spear_3=DrawaSpear(grid_3.prh2,grid_3.plh2,40);
206
207 var grid=DrawaMan(64,31,0,0,0,0.5235987755982988,-1.5707963267948966,-0.8726646259971647,-0.17453292519943298,0.8726646259971647,-0.17453292519943292,-0.8726646259971647,1.5707963267948966)
208 var spear=DrawaSpear(grid.prh2,grid.plh2,33);
209
210 var grid=DrawaMan(64,28,0,0,0,0.5235987755982988,-1.0471975511965976,-0.6981317007977318,0.17453292519943292,0.6981317007977318,-0.34906585039886584,-0.6981317007977318,1.0471975511965976)
211 var spear=DrawaSpear(grid.prh2,grid.plh2,26);
212
213 var grid_5=DrawaMan(64,25,0,0,0,Math.PI/6,-Math.PI/6,-Math.PI/6,Math.PI/6,Math.PI/6,-Math.PI/6,-Math.PI/6,Math.PI/6)
214 var spear_5=DrawaSpear(grid_5.prh2,grid_5.plh2,20);
215
216 //行走
217 var grid_5=DrawaMan(64,27,0,0,0,Math.PI/6,-Math.PI/6,-Math.PI/6,Math.PI/6,Math.PI/4,-Math.PI/4,-Math.PI/4,Math.PI/4)
218 var spear_5=DrawaSpear(grid_5.prh2,grid_5.plh2,20);
219 var grid_5=DrawaMan(64,25,0,0,0,Math.PI/6,-Math.PI/6,-Math.PI/6,Math.PI/6,Math.PI/6,-Math.PI/6,-Math.PI/6,Math.PI/6)
220 var spear_5=DrawaSpear(grid_5.prh2,grid_5.plh2,20);
221
222
223
224 linearInterpolation([Math.PI/6,-Math.PI/6,-Math.PI/6,Math.PI/6,Math.PI/6,-Math.PI/6,-Math.PI/6,Math.PI/6]
225 ,[Math.PI/6,-Math.PI*2/3,-Math.PI/3,-Math.PI/6,Math.PI/3,0,-Math.PI/3,Math.PI*2/3],2)
226     //对两个数组进行插值,参数分别是初始数组、截止数组、插值个数
227 function linearInterpolation(arrStart,arrEnd,count_inter)
228 {
229 var len=arrStart.length;
230 var arr_str=[];
231 for(var j=0;j<count_inter;j++)
232 {
233 arr_str.push(\"\");
234 }
235 for(var i=0;i<len;i++)//对于每一个属性
236 {
237 var start=arrStart[i];
238 var end=arrEnd[i];
239
240 var step=(end-start)/(count_inter+1);
241 for(var j=0;j<count_inter;j++)//对于每一个插入的值
242 {
243 arr_str[j]+=(start+step*(j+1)+\",\");
244 }
245 }
246 return arr_str;
247
248 }
249
250 </script>
251 </html>

来源:https://www.cnblogs.com/ljzc002/p/15119505.html
图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » 3D网页小实验-基于多线程和精灵动画实现RTS式单位行为

相关推荐

  • 暂无文章