Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> 基於HTML5的WebGL設計漢諾塔3D游戲

基於HTML5的WebGL設計漢諾塔3D游戲

編輯:關於android開發

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

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved