为了实现一个基于HTML5场景的小游戏,我使用了HTforWeb来实现。仅仅200行代码,我就可以用“第一人称”来进行前后上下左右的操作,实现碰撞检测。先来看看效果:http://hightopo.com/guide/gui...或者http://v.youku.com/v_show/id_...视频出现帧数的问题是我的录屏设备在实际运行过程中不会出现问题。推荐使用以上链接自行操作游玩。可以使用鼠标或触摸屏,但我认为最方便的方式是操作键盘wsad来控制上下左右。我的思路是先布局场景,代码如下:createHT([100,-20,100],'#E74C3C');createHT([-100,-20,100],'#1ABC9C');createHT([100,-20,-100],'#3498DB');createHT([-100,-20,-100],'#9B59B6');createCurve([0,-20,0]);createCircle();这些是自定义函数,createHT是描绘HT形状的图形,场景中有四个,所以调用了四次;createCurve是描绘场景中间的黄色曲线;createCircle是描绘最外层的圆,因为不是包罗万象的圆,所以也是用点画的。HT封装了一个组件ht.Shape(以下简称Shape),可以根据点自由绘制图形。可以通过shape.setPoints(pointsArray)将所有的点添加到数组中,并设置在shape中,然后通过setSegments()设置线段数组信息,即用什么方法连接两个点,即在形状手册中描述。有兴趣的可以参考HTforWebShape手册。抽其中的一个描写点的函数来看看:functioncreateHT(p3,color){shape=newht.Shape();shape.s({'shape.background':null,'shape.border.width':10,'shape.border.color':color,'all.color':color});shape.setTall(40);shape.setThickness(5);shape.setPoints([//绘制H{x:20,y:0},{x:20,y:100},{x:20,y:50},{x:80,y:50},{x:80,y:0},{x:80,y:100},//绘制T{x:120,y:0},{x:180,y:0},{x:150,y:0},{x:150,y:100}]);shape.setSegments([//绘制H1,//moveTo2,//lineTo1,//moveTo2,//lineTo1,//moveTo2,//lineTo//绘制T1,//moveTo2,//lineTo1,//moveTo2//lineTo]);形状.p3(p3);数据模型.add(形状);returnshape;}因为“HT”这个词要描述的点比较多,所以代码看起来有点大。如果你看到如何绘制一个不完整的圆,需要20行代码才能完成,包括样式,仍然会感到惊讶:shape=newht.Shape();shape.s({'shape.background':null,'shape.border.width':10,'shape.border.color':'#D26911','all.color':'#D26911'});shape.setTall(40);shape.p3(0,-20,0);shape.setThickness(10);varr=300;for(vari=0;i<36;i++){varangle=Math.PI*2*i/36;shape.addPoint({x:r*Math.cos(angle),y:r*Math.sin(angle)});}dataModel.add(shape);返回形状;场景设置好之后,下一步就是将“我”在3D中的位置显示在2D中。首先,我必须将“我”设置为“第一人称漫游模式”,直接设置g3d.setFirstPersonMode(true)即可。第一人称漫游模式的精髓在于控制眼球和中枢。如果未设置第一人称漫游模式,鼠标或触摸板将围绕中心旋转。详情请参考HTforWeb3D手册。因为HT3D封装了两个方法getEye和getCenter,这两个方法分别是获取相机的位置和目标中心点的位置。按照想象,前者就像是你头上的摄像头。中心点就是你拍摄的地方,你可以很容易地记录你的位置;后者相当于你能看到的位置,但是和我们这里不一样,因为人能看到的范围很广,但是这个中心相当于你的眼球和眼睛不能转动,某个点就在正前方你是你视线的焦点位置。了解了getEye和getCenter之后,我们就可以得到当前位置和视线位置:g2d.addTopPainter(function(g){vareye=g3d.getEye(),center=g3d.getCenter();g.fillStyle='red'g.strokeStyle='black';g.lineWidth=1;g.beginPath();g.arc(eye[0],eye[2],12,0,Math.PI*2,true);//画一个圈,实时获取“I”在3d中的位置g.fill();g.stroke();g.strokeStyle='black';g.lineWidth=2;g.beginPath();g.moveTo(eye[0],eye[2]);g.lineTo(center[0],center[2]);//画一条线,可以改变“我”和“我的视线位置”之间的线段g实时.stroke();});但是在代码中,我们发现这个方法只绘制了一次,如果不一直重绘,那么“I”在2d界面上的位置和移动是不会改变的,所以我们监听3d中属性的变化:g3d。mp(function(e){//根据“我”在3d上的位置和视线实时更新2d界面if(e.property==='eye'||e.property==='center'){//如果e属性变为get/setEye,get/setCenter,则重绘2d界面g2d.redraw();}});在2D中,我可以编辑基元并移动它的点,改变基元的大小,以及其他功能,只要基元发生变化,那么我的碰撞测试就必须更新:functionupdateBoundaries(){boundaries=[];dataModel.each(function(data){//HT曲线圆边界=boundaries.concat(ht.Default.toBoundaries(data.getPoints(),data.getSegments()));//ht.Default.toBoundaries将不连续曲线转换成Graph3dView#setBoundaries(bs)需要的参数格式});g3d.setBoundaries(boundaries);//setBoundary()可以指定碰撞边界}那么我们比较好奇的是拖动图元改变尺寸时如何保持碰撞检测?HT中有一个属性变化的监听事件addDataPropertyChangeListener(),可以简写为md()。当我们拖动一个图元时,绘制这个图元的基本点会发生变化,所以我们只需要监听这些点是否发生变化即可,这个事件的使用方法可以参考HTforWebDataModel手册dataModel.md(function(e){//数据属性改变事件if(e.property==='points'){//如果数据属性改变为getPoints/setPoints,则更新边界updateBoundaries();}});
