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

本文主要是介绍基于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 H1, // moveTo2, // lineTo1, // moveTo2, // lineTo1, // moveTo2, // lineTo// draw T1, // moveTo2, // lineTo1, // moveTo2 // 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();}
});

 

这篇关于基于HTML5及WebGL开发的2D3D第一人称漫游进行碰撞检测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120716

相关文章

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Nginx设置连接超时并进行测试的方法步骤

《Nginx设置连接超时并进行测试的方法步骤》在高并发场景下,如果客户端与服务器的连接长时间未响应,会占用大量的系统资源,影响其他正常请求的处理效率,为了解决这个问题,可以通过设置Nginx的连接... 目录设置连接超时目的操作步骤测试连接超时测试方法:总结:设置连接超时目的设置客户端与服务器之间的连接

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

CSS弹性布局常用设置方式

《CSS弹性布局常用设置方式》文章总结了CSS布局与样式的常用属性和技巧,包括视口单位、弹性盒子布局、浮动元素、背景和边框样式、文本和阴影效果、溢出隐藏、定位以及背景渐变等,通过这些技巧,可以实现复杂... 一、单位元素vm 1vm 为视口的1%vh 视口高的1%vmin 参照长边vmax 参照长边re

Python利用PIL进行图片压缩

《Python利用PIL进行图片压缩》有时在发送一些文件如PPT、Word时,由于文件中的图片太大,导致文件也太大,无法发送,所以本文为大家介绍了Python中图片压缩的方法,需要的可以参考下... 有时在发送一些文件如PPT、Word时,由于文件中的图片太大,导致文件也太大,无法发送,所有可以对文件中的图