`
xhload3d
  • 浏览: 209178 次
社区版块
存档分类
最新评论

基于HTML5的WebGL设计汉诺塔3D游戏

阅读更多

在这里我们将构造一个基于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

5
3
分享到:
评论
1 楼 1036225283 2015-11-14  
好酷,这是怎么做的

相关推荐

    基于HTML5 WebGl的VR DEMO ,(HTM5 WebGL Demo ).zip

    基于HTML5 WebGl的VR DEMO展示了如何利用WebGL技术创建沉浸式的虚拟现实环境。这个DEMO项目(WebGL-VR-master)可能包含了实现VR体验所需的各种文件,如HTML文件、JavaScript代码、CSS样式表以及可能的纹理图片和...

    HTML5 WebGL 3D 仓储管理系统

    HTML5 WebGL 3D 仓储管理系统是一种利用现代网络技术实现的高效、直观的库存管理解决方案。这个系统通过在网页上构建三维模型,为用户提供了更真实、更直观的仓库环境展示,使得库存物品的管理变得更加可视化和易于...

    HTML5+CSS+WEBGL网页3D游戏开发

    HTML5、CSS和WebGL是现代网页开发中的关键技术,它们共同为创建互动性强、视觉效果丰富的3D网页游戏提供了强大的支持。在这个经典教程中,我们将深入探讨这些技术如何结合,以构建引人入胜的网页游戏。 HTML5是超...

    基于HTML5的WebGL技术电信3D机房漫游源代码

    HTML5是下一代网页标记语言,它的出现极大地扩展了网页的交互性和功能,其中WebGL(Web Graphics Library)是一项关键的技术,它使得浏览器可以直接在用户的设备上进行硬件加速的3D图形渲染,无需任何插件。WebGL...

    基于 HTML5 WebGL 的 3D 仓储管理系统

    仓储系统!仓库管理可以说即不省力也不省事,而且使用范围还很广,数学中经常使用仓储系统来计算市场需求,物流中的动力学建模等等,所以仓储系统必不可少,在这个时间就是金钱的时代,能省时就能带来非常大的效益,...

    基于HTML5 WebGL 3D樱花飘落动画

    基于HTML5 WebGL 3D樱花飘落动画 1.网页作品简介 :HTML期末大学生网页设计作业 A+水平 ,喜欢的可以下载,文章页支持手机PC响应式布局。 2.网页作品编辑:作品下载后可使用任意HTML编辑软件(如:DW、HBuilder、...

    基于HTML5 WebGL的3D机房的示例

    用 WebGL 渲染的 3D 机房现在也不是什么新鲜事儿了,这篇文章的主要目的是说明一下,3D 机房中的 eye 和 center 的问题,刚好在项目中用上了,好生思考了一番,最终觉得这个例子最符合我的要求,就拿来作为记录。...

    基于WebGL的feng3d TypeScript 3D游戏引擎设计源码

    该项目为基于WebGL的feng3d TypeScript 3D游戏引擎设计源码,包含555个文件,涵盖454个TypeScript源文件、81个GLSL着色器文件、6个JSON配置文件、6个YAML配置文件、3个JavaScript文件、2个Markdown文件,以及若干...

    基于webGL和HTML5的网页3D动画的设计与实现.pdf

    基于WebGL和HTML5的网页3D动画的设计与实现 本文主要介绍了基于WebGL和HTML5的网页3D动画的设计与实现,讲述了如何使用WebGL将JavaScript和OpenGL ES 2.0结合在一起,实现网页中的三维可视化图像。文章还讲述了基于...

    Threejs开发指南:基于WebGL和HTML5在网页上渲染3D图形和动画.docx

    "Threejs 开发指南:基于 WebGL 和 HTML5 在网页上渲染 3D 图形和动画" 本文将对 Threejs 开发指南进行详细的介绍,包括 Threejs 的重要性、与其他 3D 渲染技术的比较、为什么要使用 Threejs 等。 首先,Threejs ...

    HTML5 WebGL酷炫3D旋转星云动画特效

    总之,"HTML5 WebGL酷炫3D旋转星云动画特效"是结合HTML5的WebGL技术和JavaScript的创新应用,通过精心设计的代码和视觉效果,为用户呈现了一种极具沉浸感的3D体验。对于想要学习WebGL或者提升网页互动性的开发者来说...

    HTML5 WEBGL 摇杆+按钮

    综上所述,"HTML5 WebGL 摇杆+按钮"的主题涵盖了WebGL的基本使用、浏览器安全策略、前端交互设计、3D动画和性能优化等多个方面,是Web开发中的一个重要实践。通过学习和实践这个项目,开发者能够提升自己的3D Web...

    基于WebGL实现3D图片特效

    总的来说,"基于WebGL实现3D图片特效"是一个结合HTML5库和WebGL技术的创新应用,通过编程技巧将2D图像转化为互动式的3D视图,为用户带来生动的视觉体验。开发者通过理解并运用JavaScript、WebGL和相关的HTML5库,...

    利用HTML5CSS3和WebGL开发HTML5游戏.zip

    此外,为了成为一名成功的HTML5游戏开发者,还需要掌握JavaScript基础,理解DOM操作,熟悉现代前端框架(如React或Vue),以及对游戏设计原理的理解。通过不断地实践和项目开发,你的技能将会不断提升,创作出更多令...

    网页动画素材 WebGL基于canvas画布绘制3D噪音线条酷炫动画特效。(抖音资料)

    网页动画素材 WebGL基于canvas画布绘制3D噪音线条酷炫动画特效。(抖音资料)网页动画素材 WebGL基于canvas画布绘制3D噪音线条酷炫动画特效。(抖音资料)网页动画素材 WebGL基于canvas画布绘制3D噪音线条酷炫动画...

    Programming 3D Applications with HTML5 and WebGL

    Create engaging 3D applications for the Web with HTML5 and the emerging web graphics standard, WebGL. With this book, you'll learn hands-on how to take your website's production value to a new level ...

    地图Web3D可视化-WebGL、Three.js

    课程分享——地图Web3D可视化-WebGL、Three.js,附源码 课程概述 - 本课程讲解如何在web上实现地图3D可视化 - 学习本课程有前端基础即可,如果了解three.js更好 适用人群 有前端基础,想基于Web实现地图数据的3D...

    HTML5+WebGL实现可拖拽的3D透明杯子效果源码.zip

    总的来说,这个项目展示了HTML5和WebGL在创建动态、交互式3D内容方面的强大能力,同时也涉及到JavaScript编程、3D图形学和用户体验设计等多个领域。对于想要学习或提高这些技能的开发者来说,这是一个非常有价值的...

Global site tag (gtag.js) - Google Analytics