搜索
首页php教程php手册基于HTML5的WebGL设计汉诺塔3D游戏

基于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  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

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),