在这里我们将构造一个基于HT for Web的HTML5+JavaScript来实现汉诺塔游戏。

http://hightopo.com/demo/hanoi_20151106/index.html

汉诺塔的游戏规则及递归算法分析请参考http://en.wikipedia.org/wiki/Tower_of_Hanoi

知道了汉诺塔的规则和算法,现在就开始创建元素。用HT for Web(http://www.hightopo.com)现有的3D模板创建底盘和3根柱子不是问题,问题是要创建若干个中空的圆盘。一开始的想法是:创建一个圆柱体,将圆柱体的上下两端隐藏,设置柱面的宽度来实现圆盘的效果,经过多次尝试并查阅相关api文档,发现柱面是没有厚度的,改方法不可行。

后来在HT for Web自定义3D模型的WebGL应用(http://www.hightopo.com/blog/381.html)受到启发,圆盘的形成就是在xy平面上的一个矩形,根据y轴旋转一周产生的,通过查阅相关文档,最总决定采用ht.Default.createRingModel方法来创建圆盘模型,然后在创建node的时候通过shape3d属性引用创建好的模型。

在逻辑实现上,采用了栈的先进后出的原理,对圆柱上的圆盘做顺序控制,确保每次移动的圆盘都是最小的圆盘。

在算法上,采用的是递归算法,通过递归算法,将搬迁过程一步一步记录下来,再采用堆的原理一步一步地执行搬迁过工作。

http://v.youku.com/v_show/id_XODcwMTk4MDI4.html

http://hightopo.com/demo/hanoi_20151106/index.html

var barNum = 5, // 圆盘个数
cylinderHeight = barNum * 20 + 40, // 圆柱高度
barrelMinORadius = 50, // 圆盘最大外半径
barrelIRadius = 10, // 圆盘内半径
poorRadius = 20, // 圆盘外半径差值
barrelMaxORadius = barrelMinORadius + barNum * poorRadius,
barrelHeight = 20, // 圆盘高
barPadding = 20, // 柱体之间的间隙
floorX = barrelMaxORadius * 6 + barPadding * 4, // 底盘长
floorY = 20, // 底盘高
floorZ = 2 * barrelMaxORadius + barPadding * 2, // 底盘宽
// 柱体集
positions = [
{
barrels: [],
position: [-(2*barrelMaxORadius + barPadding), cylinderHeight / 2 + 1, 0]
},{
barrels: [],
position: [0, cylinderHeight / 2 + 1, 0]
},{
barrels: [],
position: [(2*barrelMaxORadius + barPadding), cylinderHeight / 2 + 1, 0]
}
],
runOrder = [], // 圆盘移动顺序集
// 动画参数
params = {
delay: 10,
duration: 500,
easing: Easing['easeBoth']
}; /**
* 初始化程序
* */
function init(){
dataModel = new ht.DataModel();
g3d = new ht.graph3d.Graph3dView(dataModel);
view = g3d.getView();
view.className = 'main';
document.body.appendChild(view);
window.addEventListener('resize', function (e) {
g3d.invalidate();
}, false); g3d.setEye([0, cylinderHeight * 2, floorX * sin(2*PI/360*60)]); // 初始化节点
initNodes(); moveAnimation();
} /**
* 构造游戏移动队列
* diskQuantity:圆盘个数
* positionA:起点
* positionB:中转点
* positionC:终点
* */
function buildRunOrder(diskQuantity, positionA, positionB, positionC){
if (diskQuantity == 1) {
runOrder.push([positionA, positionC]);
} else {
buildRunOrder(diskQuantity - 1, positionA, positionC, positionB);
buildRunOrder(1, positionA, positionB, positionC);
buildRunOrder(diskQuantity - 1, positionB, positionA, positionC);
}
} /**
* 移动动画
* positionA:起点
* positionC:终点
* */
function moveAnimation(positionA, positionC){
if(!positionA){
var poses = runOrder.shift();
if(!poses){
setTimeout(reset, 500);
}else{
moveAnimation(positions[poses[0]], positions[poses[1]]);
}
}else {
var barrel = positionA.barrels.pop();
var position = positionC.cylinder.p3(),
barPos = barrel.getPosition3d();
position[1] = position[1] + floorY + barrelHeight * positionC.barrels.length - cylinderHeight / 2;
setPolylinePoints(polyline, barPos, position);
params.action = function (v, t) {
var length = g3d.getLineLength(polyline),
offset = g3d.getLineOffset(polyline, length * v),
point = offset.point,
px = point.x,
py = point.y,
pz = point.z;
barrel.p3(px, py, pz);
};
params.finishFunc = function () {
positionC.barrels.push(barrel);
var poses = runOrder.shift();
if (!poses) {
moveAnimation();
} else {
moveAnimation(positions[poses[0]], positions[poses[1]]);
}
};
anim = ht.Default.startAnim(params);
}
} /**
* 重置游戏
* */
function reset(){
if(positions[0].barrels.length == 0){
positions[0].barrels = positions[2].barrels;
}
positions[2].barrels = [];
for(var i = 0, len = positions[0].barrels.length; i < len; i++){
var pos = positions[0].cylinder.p3();
pos[1] = pos[1] + floorY + i * barrelHeight - cylinderHeight / 2;
positions[0].barrels[i].p3(pos);
}
buildRunOrder(barNum, 0, 1, 2);
setTimeout(moveAnimation, 500);
} /**
* 初始化节点
* */
function initNodes(){
// 底盘
floor = createNode([0, floorY / 2, 0], [floorX, floorY, floorZ]).s({
'shape3d': 'box',
'3d.movable': false
}); // 创建柱子
for(var i = 0, len = 3; i < len; i++){
positions[i].cylinder = createNode(positions[i].position, [20, cylinderHeight, 20], floor).s({
'shape3d': 'cylinder',
'shape3d.color': '#E5BB77',
'3d.movable': false
});
} // 创建圆盘
createBarrels(barNum, positions[0].cylinder); // 创建圆盘运行轨迹
polyline = new ht.Polyline();
polyline.setSegments([1, 2, 4, 2]);
polyline.s({
'shape.background': null,
'shape.border.color': 'rgba(0,0,0,0)',
'shape.border.gradient.color': 'rgba(0,0,0,0)',
'shape.border.pattern': [20, 10],
'shape3d.resolution': 50
});
dataModel.add(polyline);
} /**
* 设置路线节点
* */
function setPolylinePoints(polyline, from, to){
polyline.setPoints([
{x: from[0], y: from[2], e: from[1]},
{x: from[0], y: from[2], e: cylinderHeight},
{x: from[0], y: from[2], e: cylinderHeight + 60},
{x: to[0], y: to[2], e: cylinderHeight + 60},
{x: to[0], y: to[2], e: cylinderHeight},
{x: to[0], y: to[2], e: to[1]}
]);
return polyline;
} /**
* 创建圆盘
* barNum:圆盘个数
* host:吸附节点
* */
function createBarrels(barNum, host){
// 圆盘初始x位置
var pos = host.p3(); for(var i = barNum, j = 0; i > 0; i--, j++){
pos[1] = barrelHeight * j + floorY;
positions[0].barrels.push(createBarrel(pos, [1, barrelHeight, 1], barrelMinORadius + i*poorRadius, barrelIRadius, host).s({
'shape3d.color': randomColor(),
'3d.movable': false
}));
}
} /**
* 创建节点
* p3:节点位置
* s3:节点大小
* host:吸附节点
* */
function createNode(p3, s3, host){
var node = new ht.Node();
node.p3(p3);
node.s3(s3);
node.setHost(host);
node.s({
'wf.visible': 'selected',
'wf.color': '#FF6B10',
'wf.width': 2,
'wf.short': true
});
dataModel.add(node);
return node;
} /**
* 创建空心圆柱
* p3:圆桶位置
* s3:圆桶大小
* oRadius:圆桶外径
* iRadius:圆桶内径
* host:吸附节点
* */
function createBarrel(p3, s3, oRadius, iRadius, host){
return createNode(p3, s3, host).s({
'shape3d': ht.Default.createRingModel([
oRadius, 1,
oRadius, 0,
iRadius, 0,
iRadius, 1,
oRadius, 1
], null, 20, false, false, 70)
});
}

http://hightopo.com/demo/hanoi_20151106/index.html

基于HTML5的WebGL设计汉诺塔3D游戏的更多相关文章

  1. HT for Web 3D游戏设计设计--汉诺塔(Towers of Hanoi)

    在这里我们将构造一个基于HT for Web的HTML5+JavaScript来实现汉诺塔游戏. 汉诺塔的游戏规则及递归算法分析请参考http://en.wikipedia.org/wiki/Towe ...

  2. 基于 HTML5 的 WebGL 和 VR 技术的 3D 机房数据中心可视化

    前言 在 3D 机房数据中心可视化应用中,随着视频监控联网系统的不断普及和发展, 网络摄像机更多的应用于监控系统中,尤其是高清时代的来临,更加快了网络摄像机的发展和应用. 在监控摄像机数量的不断庞大的 ...

  3. 基于HTML5的WebGL实现的2D3D迷宫小游戏

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

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

    http://www.hightopo.com/demo/astar/astar.html 最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现 ...

  5. [BZOJ]1019 汉诺塔(SHOI2008)

    找规律成功次数++. Description 汉诺塔由三根柱子(分别用A B C表示)和n个大小互不相同的空心盘子组成.一开始n个盘子都摞在柱子A上,大的在下面,小的在上面,形成了一个塔状的锥形体. ...

  6. 【Python实践-3】汉诺塔问题递归求解(打印移动步骤及计算移动步数)

    # -*- coding: utf-8 -*- #汉诺塔移动问题 # 定义move(n,a,b,c)函数,接受参数n,表示3个柱子A.B.C中第1个柱子A的盘子数量 # 然后打印出把所有盘子从A借助B ...

  7. 用turtle库实现汉诺塔问题~~~~~

    汉诺塔问题 问题描述和背景: 汉诺塔是学习"递归"的经典入门案例,该案例来源于真实故事.‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬ ...

  8. Python实现汉诺塔问题的可视化(以动画的形式展示移动过程)

    学习Python已经有一段时间了,也学习了递归的方法,而能够实践该方法的当然就是汉诺塔问题了,但是这次我们不只是要完成对汉诺塔过程的计算,还要通过turtle库来体现汉诺塔中每一层移动的过程. 一.设 ...

  9. $bzoj1019-SHOI2008$ 汉诺塔 $dp$

    题面描述 汉诺塔由三根柱子(分别用\(A\ B\ C\)表示)和\(n\)个大小互不相同的空心盘子组成.一开始\(n\)个盘子都摞在柱子\(A\)上,大的在下面,小的在上面,形成了一个塔状的锥形体. ...

随机推荐

  1. ABP框架Web API跨域问题的解决方案

    ​1.在Web Api 项目下安装 Microsoft.AspNet.WebApi.Cors 包 Install-Package Microsoft.AspNet.WebApi.Cors 2.在Web ...

  2. 【转】MongoDB安全配置

    [转自]http://drops.wooyun.org/%E8%BF%90%E7%BB%B4%E5%AE%89%E5%85%A8/2470 0x00 MongoDB权限介绍 1.MongoDB安装时不 ...

  3. TDD(测试驱动开发)培训录

    2014年我一直从事在敏捷实践咨询项目,这也是我颇有收获的一年,特别是咨询项目的每一点改变,不管是代码质量的提高,还是自组织团队的建设,都能让我们感到欣慰.涉及人的问题都是复杂问题,改变人,改变一个组 ...

  4. 安装金山WPS2013造成的HTML5 file.type值异常

    处理代码的兼容性是前端攻城师们的家常便饭了,一般是对各种浏览器进行兼容性处理.但是有时候我们也会遭遇到浏览器以外的影响因素,这个是经常会被忽视掉的内容.比如前几天就听说客户端安装迅雷.暴风影音等软件会 ...

  5. Android多线程分析之一:使用Thread异步下载图像

    Android多线程分析之一:使用Thread异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处   打算整理一下对 Android F ...

  6. 如何给开源的DUILib支持Accessibility

    最近的工作是给开源的DUILib支持Accessibility, 一些经验记录并分享下. 微软的Accessibility其实Windows平台上一个挺重要的东西, 尽管在国内不受重视,但是如果你的软 ...

  7. Redis和Memcached的区别详解

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/119.html?1455855360 Redis的作者Salvatore ...

  8. Java的概述以及语法

    Java的语法分为标示符和数据类型 Java的概述: 一些手打的: long l = 12345; //隐式转换 int a = (int)121234567L; //强制转换 float f =12 ...

  9. IOS开发之控件篇UITabBarControllor第二章 - 遮掩TableView问题

    在IOS7.0以后UITabBar 里面放入一个UITableView会出现一个问题,Table会被TabBar掩盖了,当移动到最后一项的时候,永远看不到,如下面的例子,总共是99项,但是只能显示到9 ...

  10. Liferay7 BPM门户开发之42: Liferay核心JSP定制扩展

    Liferay最大的好处是不仅接口强大,利于扩展,就连JSP定制扩展都提供了3种方式. 修改核心jsp代码,有3种修改方式:1.暴力修改直接修改(位于portal-web/docroot/html), ...