MyException - 我的异常网
当前位置:我的异常网» HTML5 » 基于HTML5及WebGL开发的2D3D第一人称遨游进行碰撞检

基于HTML5及WebGL开发的2D3D第一人称遨游进行碰撞检测

www.MyException.Cn  网友分享于:2013-11-02  浏览:0次
基于HTML5及WebGL开发的2D3D第一人称漫游进行碰撞检测

为了实现一个基于HTML5的场景小游戏,我采用了HT for Web来实现,短短200行代码,我就能实现用“第一人称”来操作前进后退上下左右,并且实现了碰撞检测。

先来看下实现的效果: http://hightopo.com/guide/guide/core/3d/ht-3d-guide.html#ref_collision

或者http://v.youku.com/v_show/id_XMzA5MzUzODc4NA==.html?spm=a2h3j.8428770.3416059.1视频中出现的帧的问题是我屏幕录制器的问题,真正操作的时候不会有,建议用上面的链接自己操作玩玩,鼠标或者触屏都可以,不过我觉得最方便的还是操作键盘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()设置线段数组信息,也就是用什么样的方式来连接两点,在Shape手册中有着重描写,感兴趣的可以参考HT for Web Shape 手册。抽其中的一个描绘点的函数来看看:

function createHT(p3, color){
    shape = new ht.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([                    
        // draw 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},

        // draw T
        {x: 120, y: 0},
        {x: 180, y: 0},
        {x: 150, y: 0},
        {x: 150, y: 100}                    
    ]);                                
    shape.setSegments([
        // draw H
        1, // moveTo
        2, // lineTo
        1, // moveTo
        2, // lineTo
        1, // moveTo
        2, // lineTo

        // draw T
        1, // moveTo
        2, // lineTo
        1, // moveTo
        2 // lineTo
    ]);                
    shape.p3(p3);
    dataModel.add(shape); 
    return shape;
}

 因为“HT”这个字眼要描绘的点比较多,所以代码看起来有点大,如果你看到如何描绘一个不完全的圆用20行代码来完成,而且包括样式,还是会惊讶的:

shape = new ht.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);
                
var r = 300;
for(var i=0; i<36; i++){
    var angle = Math.PI * 2 * i / 36;
    shape.addPoint({
        x: r * Math.cos(angle),
        y: r * Math.sin(angle)
    });
}
                
dataModel.add(shape); 
return shape;

 场景设置完毕,接下来要将在3d中“我”处于的位置在2d中也显示出来。首先我得先设置“我”是“第一人称漫游模式”,直接将g3d.setFirstPersonMode(true)即可。第一人称漫游模式本质是控制eye和center,如果没有设置第一人称漫游模式,那么鼠标或者触控板拖拽会绕着center旋转。详情参考HT for Web 3D手册。

因为HT 3D中封装了两个方法getEye和getCenter,这两个方法分别是获取camera的位置和目标中心点的位置,前者按照想象来说就比方你头上有个摄像机,你走到哪里它的中心点就拍摄到哪里,可以很方便的记录你的位置;后者就相当于你看出去的位置,但是这里跟我们人不太一样,因为人是可以广度看到大范围的,但是这个center相当于你眼球和都不能转动,是正前方的某一点的位置就是你的视线聚焦位置。

了解了getEye和getCenter后我们就可以获取当前位置和视线位置了:

g2d.addTopPainter(function(g){
    var eye = 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); //绘制圆,而且还能实时获取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(); 
});

 但是在代码中我们发现,这个方法只被绘制了一次,如果不一直重绘,那么2d界面的“我”的位置和移动也是不会变的,所以我们又监听了3d中属性的变化:

g3d.mp(function(e){//根据3d上的“我”的位置和视线来实时更新2d界面
    if(e.property === 'eye' || e.property === 'center'){ //如果e属性变化为get/setEye,get/setCenter,那么重绘2d界面
        g2d.redraw();
    } 
});

 在2D中,我可以编辑图元,移动它的点,变化某个图元的大小,等等功能,只要变化了图元,那么我的碰撞测试就得更新:

function updateBoundaries(){
    boundaries = [];
    dataModel.each(function(data){//HT curve circle              
        boundaries = boundaries.concat(ht.Default.toBoundaries(data.getPoints(), data.getSegments()));
        // ht.Default.toBoundaries将不连续曲线转化成Graph3dView#setBoundaries(bs)需要的参数格式
    }); 
    g3d.setBoundaries(boundaries);//setBoundary()可指定碰撞边界
}

 那么我们好奇的点在于,如何在拖拽图元改变大小的时候还能保持碰撞检测呢?

HT中有一个对于属性变化的监听事件addDataPropertyChangeListener(),可简写为md(),在我们拖拽图元的时候,绘制这个图元的基础points就会被改变,所以我们只要监听points有没有被改变就行了,如何使用这个事件可以参考HT for Web 数据模型手册

dataModel.md(function(e){//data属性变化事件    
    if(e.property === 'points'){//如果data属性变化为getPoints/setPoints,那么更新边界
        updateBoundaries();
    }
});

 

文章评论

60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
我的丈夫是个程序员
我的丈夫是个程序员
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
一个程序员的时间管理
一个程序员的时间管理
程序员应该关注的一些事儿
程序员应该关注的一些事儿
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
那些争议最大的编程观点
那些争议最大的编程观点
10个调试和排错的小建议
10个调试和排错的小建议
Java程序员必看电影
Java程序员必看电影
程序员必看的十大电影
程序员必看的十大电影
如何成为一名黑客
如何成为一名黑客
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
中美印日四国程序员比较
中美印日四国程序员比较
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
老程序员的下场
老程序员的下场
我是如何打败拖延症的
我是如何打败拖延症的
每天工作4小时的程序员
每天工作4小时的程序员
程序员和编码员之间的区别
程序员和编码员之间的区别
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
程序员都该阅读的书
程序员都该阅读的书
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
编程语言是女人
编程语言是女人
代码女神横空出世
代码女神横空出世
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
为什么程序员都是夜猫子
为什么程序员都是夜猫子
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
旅行,写作,编程
旅行,写作,编程
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
 程序员的样子
程序员的样子
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
漫画:程序员的工作
漫画:程序员的工作
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
程序员的鄙视链
程序员的鄙视链
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有