美文网首页程序员JavaScript 进阶营前端开发笔记
基于lufylegend和cropper自定义图片的拼图华容道小

基于lufylegend和cropper自定义图片的拼图华容道小

作者: 幽小鬼 | 来源:发表于2018-11-01 17:33 被阅读2次

    前几天公司要做一个拼图的小游戏,我看到了《速度挑战 - 2小时完成HTML5拼图小游戏》,照着写完了一个小游戏以后,这几天使用cropperlufylegend游戏引擎制作了一款简单的可以自定义图片的拼图华容道游戏,该游戏除了实现基本的游戏功能以外,还支持游戏图片上传,剪切,以及图片过大可以进行压缩的功能。

    传送门

    准备

    俗话说“兵马未动粮草先行”,在直接开始撸游戏之前,需要先做一些准备:
    (1)cropper
    cropper是一款使用简单且功能强大的图片剪裁jQuery插件,我选择使用该插件来实现图片裁剪的功能,在使用之前需要引入cropper:

    <link href="https://cdn.bootcss.com/cropperjs/1.3.6/cropper.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/cropperjs/1.3.6/cropper.min.js"></script>
    

    (2)jQuery
    jQuery就不多说了,cropper就是jQuery的插件,自然需要引入,需要注意的是jQuery需要在cropper之前引入
    (3)lufylegend
    lufylegend是一个HTML5开源引擎,使用之前需要引入:

    <script src="js/lib/lufylegend-1.10.1.simple.min.js"></script>
    

    (4)WeUI
    WeUI是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。使用这个ui库主要是使用了gallery用来展示上传的图片用于下一步的裁剪,要使用的话也需要引入:

    <link rel="stylesheet" href="https://res.wx.qq.com/open/libs/weui/1.1.2/weui.min.css">
    <script type="text/javascript" src="https://res.wx.qq.com/open/libs/weuijs/1.1.3/weui.min.js"></script>
    

    开始

    在做好之前的准备以后,就可以开始撸游戏了

    1.布局

    游戏本身只需要一个div,整个页面分为两块,图片上传模块和游戏模块,整体还是比较简单,之后可以继续增加其他的内容:

    <input type="file" id="file" multiple="multiple" accept="image/*" style="display: none">
    <!--图片上传按钮-->
    <div class="weui-uploader__input-box getImg">
        <input id="getImg" class="weui-uploader__input">
    </div>
    <!--图片上传-->
    <div id="uploadPhotoBox" class="page gallery js_show img" style="display: none">
        <div class="weui-gallery" style="display: block">
            <div id="photoBox" class="photo weui-gallery__img">
                <img id="photo" style="max-width: 100%" src="">
            </div>
            <div class="tool">
                <a>
                    <i id="crop">确定</i>
                    <i id="cancel">取消</i>
                </a>
            </div>
        </div>
    </div>
    <!--游戏-->
    <div class="game" style="display: none">
        <div class="time">时间: <span id="time">99</span></div>
        <div class="steps">步数: <span id="steps">0</span></div>
        <div id="myGame"></div>
    </div>
    

    还有一点点样式:

    .time, .steps {
                position: absolute;
                margin-left: 20%;
                margin-top: 5%;
            }
    
            .steps {
                margin-top: 10%;
            }
    
            .tool {
                position: absolute;
                z-index: 2;
                background-color: #111111;
                width: 100%;
            }
    
            .tool i {
                font-size: 1rem;
                color: white;
                right: 0;
                float: right;
                padding-left: 2rem;
                padding-right: 2rem;
            }
    
            #cancel {
                float: left;
            }
    

    2.定义全局变量

    首先需要定义一些变量,并且添加一些简单的逻辑事件,例如鼠标点击:

    var imgResult;//裁剪出来图片的base64值
    var imgResultImg = new Image();//裁剪出来的图片对象
    var flObj = document.getElementById("file");
    
    $('#getImg').click(function () {
        $('#file').bind('change', function () {//文件上传控件绑定监听事件
            var file = $(this).val();
            if (file.length > 0) {//文件不为空时自动提交图片
                uploadImg();//图片提交
                $('#photoBox').css('display', 'block');
                $('.getImg').css('display', 'none');
            }
        });
        $('#file').click();
        $('#uploadPhotoBox').css('display', 'block');
    });
    
    $('#cancel').click(function () {//取消图片提交
        window.location.reload();
    });
    

    上面的uploadImg()函数会在之后有定义

    3.图片处理部分

    需要完成图片的上传,压缩,裁剪功能

    3.1 图片上传

    在用户选择文件以后要先判断是否是图片,然后再判断图片大小确定是否要压缩,然后才能开始裁剪

    function uploadImg() {//图片上传
        $('#photoBox').empty();
        $('#photoBox').html('<img id="photo" src="">');
        var file = flObj.files[0];//因为每次只上传了一张图片,所以获取到flObj.files[0];
        var fReader = new FileReader();
        var isImage = checkFile(file);//检查文件是否为图像类型
    
        if (!isImage) {
            alert("请确保文件为图像类型");
        } else {
            fReader.onload = function (e) {
                var imageSize = e.total; //图片大小
                var image = new Image();
                image.src = e.target.result;
                image.onload = function () {
                    //判断是否需要压缩图片
                    image = judgeCompress(image, imageSize);
                    document.getElementById("photo").src = image.src;
                    cropper(document.getElementById("photo"), options);
                };
            }
        }
        fReader.readAsDataURL(isImage);
    };
    

    检查文件是否为图像类型:

    function checkFile(file) {//检查文件是否为图像类型
        console.log(file);
        //使用正则表达式匹配判断
        if (!/image\/\w+/.test(file.type)) {
            return false;
        }
        return file;
    }
    

    3.2 图片压缩

    在图片压缩之前,需要先检查图片大小,图片过大才需要压缩:

    function judgeCompress(image, imageSize) {//判断图片大小
        //判断图片是否大于300000 bit
        var threshold = 300000; //阈值,可根据实际情况调整
        if (imageSize > threshold) {
            var imageData = compress(image);//图片压缩
            var newImage = new Image();
            newImage.src = imageData;
            return newImage;
        } else {
            return image;
        }
    }
    

    图片压缩是使用canvas实现,先将图片绘制出来,然后再讲绘制出来的图片保存为图片对象以完成压缩,代码实现如下:

    function compress(image) {//图片压缩
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
    
        var originWidth = image.width;
        var originHeight = image.height;
    
        var maxWidth = 800,
            maxHeight = 800;
        // 目标尺寸
        var targetWidth = originWidth,
            targetHeight = originHeight;
        // 图片尺寸超过800x800的限制
        if (originWidth > maxWidth || originHeight > maxHeight) {
            if (originWidth / originHeight > maxWidth / maxHeight) {
                // 更宽,按照宽度限定尺寸
                targetWidth = maxWidth;
                targetHeight = Math.round(maxWidth * (originHeight / originWidth));
            } else {
                targetHeight = maxHeight;
                targetWidth = Math.round(maxHeight * (originWidth / originHeight));
            }
        }
    
        canvas.height = targetHeight;
        canvas.width = targetWidth;
        ctx.drawImage(image, 0, 0, targetWidth, targetHeight);
        //压缩操作
        var quality = 0.8; //图片质量  范围:0<quality<=1 根据实际需求调正
        var imageData = canvas.toDataURL("image/jpeg", quality);
        
        return imageData;
    }
    

    3.3 图片裁剪

    得到了处理完成的图片以后,就可以进行图片裁剪了,首先先按照官网进行插件的配置,我把它们写在了一个对象中:

    var options = {
        aspectRatio: 1,  //宽高比
        preview: '.preview',  //预览窗口
        guides: true,  //裁剪框的虚线
        autoCropArea: 0.5,  //0-1之间的数值,定义自动剪裁区域的大小,默认0.8
        dragCrop: true,  //是否允许移除当前的剪裁框,并通过拖动来新建一个剪裁框区域
        movable: true,  //是否允许移动剪裁框
        resizable: true,  //是否允许改变裁剪框的大小
        zoomable: false,  //是否允许缩放图片大小
        mouseWheelZoom: false,  //是否允许通过鼠标滚轮来缩放图片
        touchDragZoom: false,  //是否允许通过触摸移动来缩放图片
        rotatable: false,  //是否允许旋转图片
        minContainerWidth: 200,  //容器的最小宽度
        minContainerHeight: 200,  //容器的最小高度
        minCanvasWidth: 0,  //canvas 的最小宽度(image wrapper)
        minCanvasHeight: 0,  //canvas 的最小高度(image wrapper)
        strict: true,
    };
    

    然后就是图片这部分最核心的裁剪部分了,但是使用cropper裁剪出来的图片是canvas,解决的方法是将canvas使用toDataURL()方法转化为base64之后再转为img对象,用于后面的操作:

    function cropper(photo, options) {//图片裁剪
        var cropper = new Cropper(photo, options);
        $('#crop').on('click', function () {
            imgResult = cropper.getCroppedCanvas().toDataURL();//裁剪出来的base64
            imgResultImg.src = imgResult;//裁剪出来的图片对象
            $('.img').css('display', 'none');
            LInit(60, "myGame", gameWidth, gameHeight, main);//游戏初始化
            $('.game').css('display', 'block');
        })
    }
    

    这样子图片处理部分就完成了,在图片裁剪完成之后就开始初始化游戏了。

    4.游戏部分

    接下来就开始游戏部分的制作,游戏中大致思路模仿了《速度挑战 - 2小时完成HTML5拼图小游戏》,在其基础上做了修改

    4.1 定义变量

    首先还是要定义游戏中需要用到的变量:

    /** 初始化游戏 */
    var gameWidth = 390;
    var gameHeight = 390;
    /** 游戏层 */
    var stageLayer, gameLayer, overLayer;
    /** 拼图块列表 */
    var blockList;
    /** 是否游戏结束 */
    var isGameOver,
        isTimeOver;
    /** 用时 */
    var startTime, time, countTime;
    /** 步数 */
    var steps;
    /** 图片 */
    var imgBmpd, startNewGame, fail, startBitmap, Again, failBitmap, againBitmap, succeed, succeedBitmap;
    
    var _blockList = [];//拼图序列
    var datalist = [];//存放图片
    

    4.2 游戏初始化

    游戏初始化,包括素材的加载,以及游戏界面的显示:

    function main() {//游戏资源初始化
        /** 全屏设置 */
        if (LGlobal.mobile) {
            LGlobal.width = gameWidth;
            LGlobal.height = gameHeight;
            LGlobal.stageScale = LStageScaleMode.SHOW_ALL;
        }
        LGlobal.screen(LGlobal.FULL_SCREEN);
        LGlobal.preventDefault = false;
    
        /** 添加加载提示 */
        var loadingHint = new LTextField();
        loadingHint.text = "资源加载中……";
        loadingHint.size = 20;
        loadingHint.x = (LGlobal.width - loadingHint.getWidth()) / 2;
        loadingHint.y = (LGlobal.height - loadingHint.getHeight()) / 2;
        addChild(loadingHint);
    
        /** 加载图片 文件*/
        LLoadManage.load(
            [
                {path: "./js/Block.js"},
                {name: "startGame", path: "./images/start.png"},
                {name: "fail", path: "./images/fail.png"},
                {name: "Again", path: "./images/challengeAgain.png"},
                {name: "succeed", path: "./images/succeed.png"},
            ],
            null,
            function (result) {
                /** 移除加载提示 */
                loadingHint.remove();
    
                /** 保存位图数据,方便后续使用 */
                imgBmpd = new LBitmapData(imgResultImg);
    
                gameInit(result);
            }
        );
    }
    
    function gameInit(e) {//游戏内容初始化
        datalist = e;
        var bitmapData = new LBitmapData(imgResultImg);
        var bitmap = new LBitmap(bitmapData);
    
        bitmap.scaleX = LGlobal.width / bitmap.width;
        bitmap.scaleY = LGlobal.height / bitmap.height;
        bitmap.width = LGlobal.width;
        bitmap.height = LGlobal.height;
        bitmap.x = 0;
        bitmap.y = 0;
        addChild(bitmap);
    
        startNewGame = new LBitmapData(datalist['startGame']);
        fail = new LBitmapData(datalist["fail"]);
        Again = new LBitmapData(datalist["Again"]);
        succeed = new LBitmapData(datalist["succeed"]);
        startBitmap = new LBitmap(startNewGame);
        failBitmap = new LBitmap(fail);
        againBitmap = new LBitmap(Again);
        succeedBitmap = new LBitmap(succeed);
    
        /** 初始化舞台层 */
        stageLayer = new LSprite();
        stageLayer.graphics.drawRect(0, "", [0, 0, LGlobal.width, LGlobal.height], true, "transparent");
        addChild(stageLayer);
    
        /** 初始化游戏层 */
        gameLayer = new LSprite();
        stageLayer.addChild(gameLayer);
    
        /** 初始化最上层 */
        overLayer = new LSprite();
        stageLayer.addChild(overLayer);
    
        /** 添加开始界面 */
        addBeginningUI();
    }
    
    function addBeginningUI() {//游戏开始界面
        var beginningLayer = new LSprite();
        beginningLayer.graphics.drawRect(0, "", [0, 0, LGlobal.width, LGlobal.height], true, "transparent");
        stageLayer.addChild(beginningLayer);
    
        /** 游戏标题 */
        var title = new LTextField();
        title.text = "拼图华容道";
        title.size = 48;
        title.weight = "bold";
        title.x = (LGlobal.width - title.getWidth()) / 2;
        title.y = 70;
        title.color = "#f8fbb5";
        title.lineWidth = 5;
        title.lineColor = "#000000";
        title.stroke = true;
        beginningLayer.addChild(title);
    
        /** 开始游戏提示 */
        startBitmap.scaleX = 0.7;
        startBitmap.scaleY = 0.7;
        startBitmap.x = (LGlobal.width - startBitmap.getWidth()) / 2;
        startBitmap.y = 250 + 0;
        beginningLayer.addChild(startBitmap);
    
        /** 初始化拼图块列表 */
        initBlockList();
        /** 打乱拼图 */
        getRandomBlockList();
    
        /** 开始游戏 */
        beginningLayer.addEventListener(LMouseEvent.MOUSE_UP, function () {
            beginningLayer.remove();
            startGame();
        });
    }
    

    4.3 游戏主体

    接下来来到了整个游戏最重要的部分,游戏主体的实现,开始以后将拼图打乱,然后进行游戏:

    (1)开始游戏

    点击界面以后将游戏的各种值初始化,然后开始游戏

    function startGame() {//开始游戏
        isGameOver = false;
        isTimeOver = false;
    
        /** 初始化时间和步数 */
        startTime = (new Date()).getTime();
        countTime = 0;
        time = 0;
        steps = 0;
    
        /** 显示拼图 */
        showBlock();
        /** 计时 */
        updateTimeTxt(countTime);
        /** 显示步数 */
        updateStepsTxt();
    
        stageLayer.addEventListener(LEvent.ENTER_FRAME, onFrame);
    }
    
    (2)显示拼图

    显示拼图显然不是一张图,那么就需要拼图块,后面会定义一个类来表示这些拼图块

    function showBlock() {//显示拼图
        for (var i = 0, l = blockList.length; i < l; i++) {
            var b = blockList[i];
    
            /** 根据序号计算拼图块位置 */
            var y = (i / 3) >>> 0, x = i % 3;
    
            b.setLocation(x, y);
    
            gameLayer.addChild(b);
        }
    }
    
    (3)初始化拼图列表

    根据序号计算拼图块图片显示位置,将拼图块存放到列表中

    function initBlockList() {//初始化拼图列表
        blockList = new Array();
    
        for (var i = 0; i < 9; i++) {
            /** 根据序号计算拼图块图片显示位置 */
            var y = (i / 3) >>> 0, x = i % 3;
            blockList.push(new Block(i, x, y));
        }
    }
    
    (4)打乱拼图

    这里使用的是随机打乱拼图,然后计算序列的倒序和,如果倒序和是奇数,拼图无法完成,需要重新打乱,直到倒序和为偶数。

    function getRandomBlockList() {//随机打乱拼图
    
        /** 随机打乱拼图 */
        blockList.sort(function () {
            return 0.5 - Math.random();
        });
    
        /** 计算逆序和 */
        var reverseAmount = 0;
    
        for (var i = 0, l = blockList.length; i < l; i++) {
            var currentBlock = blockList[i];
    
            for (var j = i + 1; j < l; j++) {
                var comparedBlock = blockList[j];
    
                if (comparedBlock.index < currentBlock.index) {
                    reverseAmount++;
                }
            }
        }
    
        /** 检测打乱后是否可还原 */
        if (reverseAmount % 2 != 0) {
            /** 不合格,重新打乱 */
            getRandomBlockList();
        } else {
            var str = "";
            for (var i = 0; i < blockList.length; i++) {
                str = str + blockList[i].index;
            }
            console.log(str);
            if (str.substr(0, 3) == "012") {
                getRandomBlockList();
            } else {
                _blockList.push(str);
            }
        }
    }
    

    4.4 拼图块

    在拼图过程中,引入了一个新的Block类,这个类用来表示并且操作拼图块:

    function Block(index, x, y) {
        LExtends(this, LSprite, []);
    
        var bmpd = imgBmpd.clone();
        if (index != 8) {
            bmpd.setProperties(x * bmpd.width / 3, y * bmpd.width / 3, bmpd.width / 3, bmpd.width / 3);
            this.bmp = new LBitmap(bmpd);
            this.bmp.scaleX = 130 / this.bmp.width;
            this.bmp.scaleY = 130 / this.bmp.height;
            this.addChild(this.bmp);
        } else {
            var shape = new LShape();
            shape.graphics.drawRect(2, "#ffffff", [0, 0, 130, 130], true, "#ffffff");
            this.addChild(shape);
        }
    
        // 格子边框
        var border = new LShape();
        border.graphics.drawRect(3, "#ffffff", [0, 0, 130, 130]);
        border.graphics.drawRoundRect(3, "#ffffff", [0, 0, 130, 130, 10]);
        this.addChild(border);
    
        this.index = index;
    
        this.addEventListener(LMouseEvent.MOUSE_UP, this.onClick);
    }
    
    Block.getBlock = function (x, y) {
        return blockList[y * 3 + x];
    };
    
    Block.isGameOver = function () {
        var reductionAmount = 0, l = blockList.length;
    
        /** 计算还原度 */
        for (var i = 0; i < l; i++) {
            var b = blockList[i];
    
            if (b.index == i) {
                reductionAmount++;
            }
        }
    
        /** 计算是否完全还原 */
        if (reductionAmount == l) {
            /** 游戏结束 */
            gameOver();
        }
    };
    
    Block.exchangePosition = function (b1, b2) {
        var b1x = b1.locationX, b1y = b1.locationY,
            b2x = b2.locationX, b2y = b2.locationY,
            b1Index = b1y * 3 + b1x,
            b2Index = b2y * 3 + b2x;
    
        /** 在地图块数组中交换两者位置 */
        blockList.splice(b1Index, 1, b2);
        blockList.splice(b2Index, 1, b1);
    
        /** 交换两者显示位置 */
        b1.setLocation(b2x, b2y);
        b2.setLocation(b1x, b1y);
    
        /** 判断游戏是否结束 */
        Block.isGameOver();
    };
    
    Block.prototype.setLocation = function (x, y) {//方块位置
        this.locationX = x;
        this.locationY = y;
    
        this.x = x * 130;
        this.y = y * 130 + 0;
    };
    
    Block.prototype.onClick = function (e) {//方块的点击事件
        var self = e.currentTarget;
    
        if (isGameOver) {
            return;
        }
    
        var checkList = new Array();
    
        /** 判断右侧是否有方块 */
        if (self.locationX > 0) {
            checkList.push(Block.getBlock(self.locationX - 1, self.locationY));
        }
    
        /** 判断左侧是否有方块 */
        if (self.locationX < 2) {
            checkList.push(Block.getBlock(self.locationX + 1, self.locationY));
        }
    
        /** 判断上方是否有方块 */
        if (self.locationY > 0) {
            checkList.push(Block.getBlock(self.locationX, self.locationY - 1));
        }
    
        /** 判断下方是否有方块 */
        if (self.locationY < 2) {
            checkList.push(Block.getBlock(self.locationX, self.locationY + 1));
        }
    
        for (var i = 0, l = checkList.length; i < l; i++) {
            var checkO = checkList[i];
    
            /** 判断是否是空白拼图块 */
            if (checkO.index == 8) {
                steps++;
                updateStepsTxt();
    
                Block.exchangePosition(self, checkO);
                var str = "";
                for (var i = 0; i < blockList.length; i++) {
                    str = str + blockList[i].index;
                }
                _blockList.push(str);
    
                break;
            }
        }
    };
    

    4.5 游戏结束

    添加游戏结束功能,根据拼图完成或者计时结束判断游戏成功或是失败

    (1)游戏计时计步

    游戏未结束之前更新游戏的时间和步数:

    function onFrame() {//计时
    
        if (isGameOver) {
            return;
        }
        if (isTimeOver) {
            return;
        }
        /** 获取当前时间 */
        var currentTime = (new Date()).getTime();
    
        /** 计算使用的时间并更新时间显示 */
        time = currentTime - startTime;
    
        if (countTime > 0) {// 倒计时
            updateTimeTxt();
        } else {
            timeOver();
        }
    }
    
    (2)更新时间和步数
    function updateTimeTxt() {//更新时间
        $('#time').html(getTimeTxt());
    }
    
    function getTimeTxt() {
        var d = new Date(time);
        countTime = 99 - Math.floor(d / 1000);
        return countTime;
    }
    
    function updateStepsTxt() {//更新步数
        $('#steps').html(steps);
    }
    
    (3)游戏失败

    游戏时间结束后视为游戏失败,弹出游戏失败界面,点击重新开始

    function timeOver() {// 判断时间是否结束 失败
        isTimeOver = true;
    
        var resultLayer = new LSprite();
        resultLayer.filters = [new LDropShadowFilter()];
        resultLayer.graphics.drawRoundRect(3, "#BBBBBB", [0, 0, 390, 450, 5], true, "rgba(0,0,0,.6)");
        resultLayer.x = (LGlobal.width - resultLayer.getWidth()) / 2;
        resultLayer.y = LGlobal.height / 2;
        resultLayer.alpha = 0;
        overLayer.addChild(resultLayer);
    
        failBitmap.scaleX = 0.6;
        failBitmap.scaleY = 0.6;
        failBitmap.x = (LGlobal.width - failBitmap.getWidth()) / 2;
        failBitmap.y = 70 + 0;
        resultLayer.addChild(failBitmap);
    
        againBitmap.scaleX = 0.6;
        againBitmap.scaleY = 0.6;
        againBitmap.x = (LGlobal.width - againBitmap.getWidth()) / 2;
        againBitmap.y = 250 + 0;
        resultLayer.addChild(againBitmap);
    
        LTweenLite.to(resultLayer, 0.5, {
            alpha: 0.7,
            y: (LGlobal.height - resultLayer.getHeight()) / 2 - 15,
            onComplete: function () {
                /** 点击界面重新开始游戏 */
                stageLayer.addEventListener(LMouseEvent.MOUSE_UP, function () {
                    gameLayer.removeAllChild();
                    overLayer.removeAllChild();
                    stageLayer.removeAllEventListener();
                    main();
                });
            }
        });
    }
    
    (4)游戏成功

    拼图完成时游戏成功,弹出游戏成功界面,输出游戏用时,步数,分数以及游戏情况的序列,点击重新开始

    function gameOver() {// 游戏成功
        let score = 99 - getTimeTxt(time);
        let blockList = _blockList.join("-");
        let step = steps;
        isGameOver = true;
        console.log('用时:' + getTimeTxt(time) + '步数:' + step + '分数:' + score + '序列:' + blockList);
    
        var resultLayer = new LSprite();
        resultLayer.filters = [new LDropShadowFilter()];
        resultLayer.graphics.drawRoundRect(3, "#BBBBBB", [0, 0, 390, 450, 5], true, "rgba(0,0,0,.6)");
        resultLayer.x = (LGlobal.width - resultLayer.getWidth()) / 2;
        resultLayer.y = LGlobal.height / 2;
        resultLayer.alpha = 0;
        overLayer.addChild(resultLayer);
    
        succeedBitmap.scaleX = 0.6;
        succeedBitmap.scaleY = 0.6;
        succeedBitmap.x = (LGlobal.width - succeedBitmap.getWidth()) / 2;
        succeedBitmap.y = 70 + 0;
        resultLayer.addChild(succeedBitmap);
    
        againBitmap.scaleX = 0.6;
        againBitmap.scaleY = 0.6;
        againBitmap.x = (LGlobal.width - againBitmap.getWidth()) / 2;
        againBitmap.y = 250 + 0;
        resultLayer.addChild(againBitmap);
    
        LTweenLite.to(resultLayer, 0.5, {
            alpha: 0.7,
            y: (LGlobal.height - resultLayer.getHeight()) / 2 - 15,
            onComplete: function () {
                /** 点击界面重新开始游戏 */
                stageLayer.addEventListener(LMouseEvent.MOUSE_UP, function () {
                    gameLayer.removeAllChild();
                    overLayer.removeAllChild();
                    stageLayer.removeAllEventListener();
                    main();
                });
            }
        });
    }
    

    反思和总结

    感受

    终于撸完了这个简单的小游戏,虽然写的毛毛糙糙,很多地方写得也不够好,但是收获肯定是有的,不光是看了文档,学习了大佬们的思路,同时也增长了一些动手能力,虽然代码比较简单,但是只要坚持,日积月累肯定会有收获。

    可优化项

    在写这篇博客的时候,回顾代码就已经满满的槽点了,把可优化项记录下来,以后有空可以尝试去优化:

    • 1.使用jQuery和原生js两种方式获取dom元素,编码习惯不好,使代码更加混乱
    • 2.游戏白底界面过于简单
    • 3.随机打乱拼图,使游戏无法设置多种难度,缺少游戏乐趣
    • 4.图片裁剪部分布局粗糙使用WeUI来完成
    • 5.无法保留游戏记录

    相关文章

      网友评论

        本文标题:基于lufylegend和cropper自定义图片的拼图华容道小

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