文档章节

基于HTML5的WebGL呈现A星算法的3D可视化

xhload3d
 xhload3d
发布于 2015/11/17 23:41
字数 938
阅读 418
收藏 15

最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现,算法基于开源 https://github.com/bgrins/javascript-astar 的javascript实现,其实作者也有个不错的2D例子实现 http://www.briangrinstead.com/files/astar/ ,只不过觉得所有A*算法的可视化实现都是平面的不够酷,另外还有不少参数需要调节控制,还是值得好好搞个全面的Demo,先上张2D和3D例子的对照图。http://www.hightopo.com/demo/astar/astar.html

Screen Shot 2014-11-24 at 5.36.33 PM

实现代码比较容易一百多行,不过算法核心在astar.js了,界面核心在ht.js里面了,我只需要构建网格信息,只需监听用户点击,然后调用astar.js进行最短路径计算,将结果通过动画的方式呈现出走动的过程,所有代码如下:

function init() {                
	w = 40; m = 20; d = w * m / 2;            
	gridRows = [];                        
	dm = new ht.DataModel();             
	g3d = new ht.graph3d.Graph3dView(dm);                
	g3d.setGridVisible(true);
	g3d.setGridColor('#BBBBBB');
	g3d.setGridSize(m);
	g3d.setGridGap(w);            
	g3d.addToDOM();                                                                                                        
	g3d.sm().setSelectionMode('none');            
	anim = startBall = endBall = null;                        
	g3d.getView().addEventListener(ht.Default.isTouchable ? 'touchstart' : 'mousedown', function(e){                
		if(!anim){
			var p = g3d.getHitPosition(e);
			var x = Math.floor((p[0] + d)/ w);
			var y = Math.floor((p[2] + d)/ w);
			var endBall = dm.getDataByTag("cell_" + x + "_" + y);
			if(endBall && endBall.s('batch') !== 'wall'){                      
				if(startBall.a('x') === x && startBall.a('y') === y){
					return;
				}                        
				var g = new Graph(gridRows, { 
					diagonal: formPane.v('diagonal') 
				});
				var start = g.grid[startBall.a('x')][startBall.a('y')];
				var end = g.grid[x][y];
				var result = astar.search(g, start, end, {
					closest: formPane.v('closest')                            
				});  
				if(!result.length){
					return;
				}
				x = result[result.length-1].x;
				y = result[result.length-1].y;
				endBall = dm.getDataByTag("cell_" + x + "_" + y);
				endBall.s('3d.visible', true);
				startBall.s('3d.visible', false);
				formPane.setDisabled(true);
				anim = ht.Default.startAnim({
					duration: 700,
					finishFunc: function(){  
						for(var i=0; i<result.length; i++){
							var ball = dm.getDataByTag("cell_" + result[i].x + "_" + result[i].y);
							ball.s({
								'3d.visible': false,
								'shape3d.opacity': 1,
								'shape3d.transparent': false
							}); 
							startBall.p3(-d+w*x+w/2, w/2, -d+w*y+w/2);
							startBall.a({x: x, y: y});
							startBall.s('3d.visible', true);
						}
						anim = null;
						formPane.setDisabled(false);
					},
					action: function(v){
						var index = Math.round(v*result.length);
						for(var i=0; i<index; i++){
							var ball = dm.getDataByTag("cell_" + result[i].x + "_" + result[i].y);
							ball.s({
								'3d.visible': true,
								'shape3d.opacity': i/index*0.3 + 0.7,
								'shape3d.transparent': true
							});                                    
						}
					}
				});                                                
			}
		}               
	}, false);                                    
	createFormPane();
	createGrid();                                
}                
function createGrid(){
	dm.clear();            
	var ball;
	gridRows.length = 0;
	for(var x = 0; x < m; x++) {
		var nodeRow = [];
		gridRows.push(nodeRow);
		for(var y = 0; y < m; y++) {                                
			var isWall = Math.floor(Math.random()*(1/formPane.v('frequency')));
			if(isWall === 0){
				nodeRow.push(0);
				createNode(x, y).s({
					'batch': 'wall',
					'all.color': '#9CA69D'
				});
			}else{
				nodeRow.push(1);
				ball = createNode(x, y).s({
					'shape3d': 'sphere',  
					'shape3d.color': '#FF703F',
					'3d.visible': false
				});
			}            
		}       
	}
	if(!ball){
		createGrid();
		return;
	}            
	startBall = createNode(ball.a('x'), ball.a('y'), 'start').s({
		'shape3d': 'sphere',  
		'shape3d.color': '#FF703F'                    
	});  

	shape = new ht.Shape();
	shape.setPoints(new ht.List([
		{x: -d, y: d},
		{x: d, y: d},
		{x: d, y: -d},
		{x: -d, y: -d},
		{x: -d, y: d}
	]));
	shape.setThickness(4);
	shape.setTall(w);
	shape.setElevation(w/2);
	shape.setClosePath(true);
	shape.s({
		'all.color': 'rgba(187, 187, 187, 0.8)', 
		'all.transparent': true, 
		'all.reverse.cull': true
	});
	dm.add(shape);                            
}
function createNode(x, y, tag){
	var node = new ht.Node();
	tag = tag || "cell_" + x + "_" + y;               
	node.setTag(tag);            
	node.a({ x: x,  y: y });
	node.s3(w*0.9, w*0.9, w*0.9);
	node.p3(-d+w*x+w/2, w/2, -d+w*y+w/2);
	node.s({
		'all.reverse.cull': true,
		'shape3d.reverse.cull': true
	});
	dm.add(node);
	return node;
}                       
function createFormPane() {           
	formPane = new ht.widget.FormPane();
	formPane.setWidth(230);
	formPane.setHeight(70);
	formPane.getView().className = 'formpane';
	document.body.appendChild(formPane.getView());            
	formPane.addRow(['Wall Frequency', {
		id: 'frequency',
		slider: {
			min: 0,
			max: 0.8,
			value: 0.1,                            
			onValueChanged: function(){
				createGrid();
			}
		}
	}], [100, 0.1]);                               
	formPane.addRow([
		{
			id: 'closest',
			checkBox: {
				label: 'Try Closest'
			}
		},
		{
			id: 'diagonal',
			checkBox: {
				label: 'Allow Diagonal'
			}        
		}
	], [0.1, 0.1]);
}

自从iOS8支持WebGL后在移动终端上测试3D应用比当前的大部分Android平板舒服多了,以上的例子在iOS系统下呈现和算法都挺流畅,http://v.youku.com/v_show/id_XODMzOTU1Njcy.html,当然这个小例子数据量也不大,本质其实还是2D的最短路径算法,并非真正意义的3D空间最短路径,但还是足够解决很多实际应用问题了。http://www.hightopo.com/demo/astar/astar.html

Screen Shot 2014-11-24 at 5.09.13 PM


© 著作权归作者所有

xhload3d
粉丝 194
博文 174
码字总数 362206
作品 0
崇明
私信 提问
精选9个值得学习的 HTML5 效果【附源码】

这里精选了一组很酷的 HTML5 效果。HTML5 是现 Web 开发领域的热点, 拥有很多让人期待已久的新特性,特别是在移动端,Web 开发人员可以借助 HTML5 强大功能轻松制作各种交互性强、效果丰富的...

赵小宾
2014/11/27
423
0
基于HTML5实现的Heatmap热图3D应用

Heatmap热图通过众多数据点信息,汇聚成直观可视化颜色效果,热图已广泛被应用于气象预报、医疗成像、机房温度监控等行业,甚至应用于竞技体育领域的数据分析。 已有众多文章分享了生成Heatm...

xhload3d
2014/09/12
6.6K
35
[HTML5] 关于HTML5(WebGL)的那点事

2013年新春伊始,HTML5的曝光率急速增加,可以预见的是今年HTML5必将随着移动互联网的扩张而大举入侵!作为互联网前沿工作者的我们怎能视而不见!赶紧来认识一下HTML5家族中的主要新成员。 ...

长平狐
2013/07/01
2.9K
0
八大疯狂的 HTML5 Canvas 及 WebGL 动画效果

HTML5、WebGL和JavaScript改变了长久以来的动画制作行业。在过去的几年中,我们想要制作卓越的网页动画只能使用Flash和Java Applet。而现在,使用脚本语言和渲染器在浏览器中实现疯狂的动画效...

红薯
2012/03/14
6.8K
8
基于Web的3D绘图标准 —— WebGL发布1.0版本

Khronos 组织在游戏开发者大会发布了 WebGL 规范 1.0 正式版本,该版本带来了全新的 OpenGL ES 2.0,使得浏览器可通过 HTML5 和 JavaScript 进行识别,这表明 WebGL 将逐渐进入我们的视野。 ...

红薯
2011/03/04
1K
6

没有更多内容

加载失败,请刷新页面

加载更多

Android面试常客之Handler全解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/fnhfire_7030/article/details/79518819 前言:又到了一年...

shzwork
5分钟前
0
0
position sticky 定位

本文转载于:专业的前端网站➫position sticky 定位 1、兼容性 https://caniuse.com/#search=sticky chrome、ios和firefox兼容性良好。 2、使用场景 sticky:粘性。粘性布局。 在屏幕范围内时...

前端老手
11分钟前
1
0
CentOS 7 yum 安装 PHP7.3 教程

参考:https://www.mf8.biz/centos-rhel-install-php7-3/ 1、首先安装 EPEL 源: yum install epel-release 安装 REMI 源: yum install http://rpms.remirepo.net/enterprise/remi-release......

dragon_tech
26分钟前
1
0
Linux物理网卡聚合及桥接

Linux内部实现的bridge可以把一台机器上的多张网卡桥接起来,从而把自己作为一台交换机。同时,LInux bridge还支持虚拟端口,即桥接的不一定都是物理网卡接口,还可以是虚拟接口。目前主要表...

xiangyunyan
27分钟前
1
0
一起来学Java8(一)——函数式编程

在这篇文章中,我们将了解到在Java8下如何进行函数式编程。 函数式编程 所谓的函数式编程就是把函数名字当做值进行传递,然后接收方拿到这个函数名进行调用。 首先来看下JavaScript如何进行函...

猿敲月下码
58分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部