美文网首页
微信小程序——用canvas做个层叠消融游戏(一)

微信小程序——用canvas做个层叠消融游戏(一)

作者: KroketTian | 来源:发表于2018-06-14 17:03 被阅读0次

    本篇为小程序的一学习笔记,以一小游戏‘层叠消融’为例子,对canvas组件进行展开学习。

    开场白就没了,直奔主题。先来看看小程序在组件使用上,对canvas做了什么。

    em……,首先,指定了作为唯一标识符的属性canvas-id,因为小程序搭了一套MV*框架,所以对于元素绑定这个,和用原生的js的方式不同。然后就是一系列的手势触发事件。其他的,其实在使用上也没做什么特别的处理嘛。既然如此,那就直接贴上对canvas进行元素绑定的代码吧。

    <!-- canvas.wxml -->

    <canvas canvas-id="testCanvas"></canvas>

    <!-- canvas.js -->

    Page({

        onReady: function(e) {

            // 使用wx.createContext获取绘图上下文 context

            var context = wx.createCanvasContext('testCanvas');

            context.setStrokeStyle('#00ff00');

            context.rect(0,0,200,200);

            context.draw();

        }

    })

    因为小程序的canvas元素默认宽高是不会覆盖全屏的,所以在初始化canvas之后要进行重新设置宽高。屏幕的宽高可以通过API:wx.getSystemInfo获得。

    接下来就是画图了。‘层叠消融’这个游戏的主要效果就是图片叠加部分双数相消。具体效果如图:

    上面的图形由三个基本图形(正方形)组成,用这三个基本图形拼出上面的目标图案,则算通关。

    需求:多图形相叠双数相消。要实现这个效果,用传统的css是很麻烦的,这时canvas的灵活性就体现出来了。canvas对图片图形的处理是像素级的,其本身提供了一系列的图形遮盖策略。globalCompositeOperation这个属性设定了在画新图形时采用的遮盖策略,其值是一个标识12种遮盖方式的字符串。其中‘xor’方式正能实现我们双数相消的需求。

    立即贴上主要的代码:

    //绘制一个反相图案

    let revert = function(path){

        this.context.beginPath();

        this.context.fillStyle="#000";

        this.context.globalCompositeOperation="xor";

        for(let i=0;i<path.length;i++){

            if(i==0){

                this.context.moveTo(path[i].x,path[i].y);

            }else{

                this.context.lineTo(path[i].x,path[i].y);

            }

        }

        this.context.fill();

        return this;

    }

    (小程序的onReady函数,这里具体的调用我打包了一下,具体打包细节我就不再这里细讲了)

    onReady: function(){

        let canvasCtl = new this.canvasCtl();

        canvasCtl.init(this);

        let block1 = new util.block([{x:200,y:50},{x:100,y:150},{x:100,y:50}],canvasCtl);

        block1.initBlock();

        let block2 = new util.block([{x:150,y:70},{x:250,y:70},{x:250,y:200}],canvasCtl);

        block2.initBlock();

        let block3 = new util.block([{x:50,y:60},{x:110,y:60},{x:110,y:110},{x:50,y:110}],canvasCtl);

        block3.initBlock();

        this.blockList.push(block1);

        this.blockList.push(block2);

        this.blockList.push(block3);

    },

    效果图如下:

    既然是小游戏,那就要会动是不是。需求:手指点上时,选中图片跟着移动。

    这时,就要用上小程序给我们提供的手势触发了,用到的有这两个:

    bindtouchstart用于判断手指选中那个图形,bindtouchmove用于图形移动。

    对于判定选中图形这个问题,赶紧回忆起你的小学数学:沿着判定点向图形方向画一条射线,若相交点为单数,则判定点在图形中,否则,判定点在图形外。转换为代码模式如下:

    block.prototype.checkPointInRegion = function(pt){

        let nCross = 0; // 定义变量,统计目标点向右画射线与多边形相交次数

        for (let i = 0; i < this.path.length; i++) { //遍历多边形每一个节点

            let p1 = this.path[i];

            let p2 = this.path[(i+1)%this.path.length];

            // p1是这个节点,p2是下一个节点,两点连线是多边形的一条边

            // 以下算法是用是先以y轴坐标来判断的

            if ( p1.y == p2.y )continue;//如果这条边是水平的,跳过

            if ( pt.y < ((p1.y= ((p1.y>p2.y)?p1.y:p2.y))continue;//如果目标点高于这个线段,跳过

            //那么下面的情况就是:如果过p1画水平线,过p2画水平线,目标点在这两条线中间

            let x = (pt.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;

            // 这段的几何意义是 过目标点,画一条水平线,x是这条线与多边形当前边的交点x坐标

            if ( x > pt.x ) nCross++; //如果交点在右边,统计加一。这等于从目标点向右发一条射线(ray),与多边形各边的相交(crossing)次数

        }

        if (nCross % 2 == 1) {

            return true; //如果是奇数,说明在多边形里

        } else {

            return false; //否则在多边形外 或 边上

        }

    }

    下面就是移动了,canvas的图形的移动很粗暴,那就是擦掉旧的重新画上新的。需要记录下多次bindtouchmove触发时手指的位移->计算出图形移动后的新定点坐标->在画布上擦掉旧图形->根据新坐标画上新图形。下面贴上主要代码:

    searchBlock:function(e){ 

        if(this.movePath.length>10){ 

             this.movePath.shift(); 

         }

         this.movePath.push(e);

        for(let i = 0; i < this.blockList.length; i++){//让新选中的图形永远处于第一位

          if(this.blockList[i].checkPointInRegion({ x: e.touches[0].x , y:e.touches[0].y })){

            [this.blockList[0],this.blockList[i]] = [this.blockList[i],this.blockList[0]]

          };

        }

      }, 

     moveBlock:function(e){

        if(this.movePath.length>10){

          this.movePath.shift();

        }

        this.movePath.push(e);

        let oldPath = this.movePath[this.movePath.length-2]?this.movePath[this.movePath.length-2]:null;

        let newPath = e;

        this.blockList[0].move(oldPath.touches[0],newPath.touches[0]);

      },

    block.prototype.move = function(oldPath,newPath){

        if(oldPath){

          var x = newPath.x - oldPath.x;

          var y = newPath.y - oldPath.y;

          this.changeLocation(x,y);

        }

    }

    效果图如下:

    接下去就是通关判定、关卡设置、关卡选择……有点多,这些内容就留到下期吧。

    相关文章

      网友评论

          本文标题:微信小程序——用canvas做个层叠消融游戏(一)

          本文链接:https://www.haomeiwen.com/subject/xbbyeftx.html