微信小游戏排行榜的原生显示

前言

       微信小游戏开放了好友关系链,使得小游戏的社交能力得到了加强,有助于增加游戏的活跃度。出于安全限制,只能在开放域使用关系链数据,但是开放域是独立的工程,使得包体变大不小,所以笔者写了一个简单的渲染核心,既保留API一致,占用空间也很少。

节点树结构

       先模拟一个简单的节点树结构,以便使用父子这样的结构代码,符合一般的引擎风格。

function Node{
    this.x = 0
    this.y = 0
    ...  
}

通用方法定义:

Node.prototype ={
    setPosition(x, y) {
        this.x = x
        this.y = y
        this.isDirty = true
    },
    _updateWorldMatrix(){
        this.worldMatrix = this.parent ? matMul(this.localMatrix, this.parent.worldMatrix) : this.localMatrix
    }
    ...
}

渲染核心

function render(){
//重置转换矩阵
    context.setTransform(1, 0, 0, 1, 0, 0);
    //清空画布
    context.clearRect(0, 0, canvas.width, canvas.height);

    var draw = function (node, bUpdate) {
        var redraw = node.isDirty || bUpdate
        if (redraw) {
            //更新变动部分的矩阵
            node._updateWorldMatrix()
        }
        //Y轴 翻转,向下平移一个画布高度
        context.setTransform(1, 0, 0, -1, 0, canvas.height);

        if (node.type) {
            var t = node.worldMatrix
            context.transform(t[0], t[1], t[3], t[4], t[6], t[7])
            context.scale(1, -1);
        }
        if (node.bClip) {
            context.save()
            //剪裁
            ...
        }
        if (node.type == "sprite") {
            //精灵
            ...
        }
        if (node.type == "label") {
            //文字
            ...
        }
        node.children.forEach(v => draw(v, redraw))
        if (node.bClip) {
            //剪裁区域绘制完,恢复画布
            context.restore();
        }
        node.isDirty = false
    }
    draw(scene)
}

以上是实际绘制的部分,比较多,所以只写了大概的结构,详细的请看源码链接。
引擎2d渲染部分原理大概是这样,看明白后,会对游戏引擎的核心部分有更加深入的理解。

触摸事件响应

由于需要制作排行榜,有些需要滚动的,那么要监听并分发触摸事件,以响应用户行为。
先做一个统一的事件分发机制:

function handleEvent(name, event) {
    var pt = event.changedTouches[0]
    scene.forEach(child=>{
        if (child.getBoundingBox().contains(pt)){
            if (child.listener[name]) {
                child.listener[name](pt)
            }
        }
    }
}

监听微信的触摸事件接口:

wx.onTouchStart(e => handleEvent("onTouchBegan", e))
wx.onTouchMove(e => handleEvent("onTouchMove", e))
wx.onTouchEnd(e => handleEvent("onTouchEnded", e))
wx.onTouchCancel(e => handleEvent("onTouchCancel", e))

小结

       实际上是写了一个微小的渲染引擎,便于扩展,容易理解学习。篇幅有限,不能展示所有的细节部分,有兴趣的可以查看源码渲染核心demo

阅读 1.2k

推荐阅读