pixi.js制作简单拼图互动demo

 基于vue的小demo

拖动拼图块,组成拼图

<!-- 多余类名可去掉 -->
<canvas ref="canvasDom" class="lcter scene-canvas" id="canvas"></canvas>

 我的vue文件里面引入的东西

import * as PIXI from 'pixi.js'
import { onMounted, ref } from 'vue'

 相关逻辑代码,有部分代码涉及到pixi的loader问题。

我是提前使用loader加载项目所有用到的切图后存起来的,然后使用进度条的方式展现在最高层,这样用户进入页面时候会先提示进度条,代表资源加载进度。

const app = ref()
// 这一块是我们项目中已经有对项目的静态资源统一进行了加载,这里我就不做加载模块的展示啦
// 你们自行百度一下pixi加载静态资源 自行根据资源加载和取名
// 你们自行去用pixi的load对资源进行加载即可 不懂的话 百度有 
const textureList = PIXI.utils.TextureCache;
const canvasDom = ref(null);

// 定义碎片的信息数组
const puzzleArr = [
    {
        id: 0,
        name: 'puzzle_item01.png',
        x: 620,
        y: 470,
        correct: false,
    },
    {
        id: 1,
        name: 'puzzle_item02.png',
        x: 660,
        y: 280,
        correct: false,
    },
    {
        id: 2,
        name: 'puzzle_item03.png',
        x: 980,
        y: 480,
        correct: false,
    },
    {
        id: 3,
        name: 'puzzle_item04.png',
        x: 960,
        y: 300,
        correct: false,
    },


]
// 定义正确的位置
const correctPosition = [
    {
        x2: 812,
        y2: 284
    },
    {
        x2: 864,
        y2: 458
    },
    {
        x2: 760,
        y2: 460
    },
    {
        x2: 811,
        y2: 572
    },
]

// 等页面初始化完成后才能获取到dom
onMounted(() => {
    app.value = new PIXI.Application({
        view: canvasDom.value,
        width: 1624,
        height: 750,
        backgroundColor: 0xb2b2b2,
        resolution: window.devicePixelRatio || 1,
        antialias: true, //抗锯齿
    });
});

// 这里我直接全部写进一个函数 方便进入页面直接调用即可
const puzzleDemo = () => {
    // 定义碎片的信息数组
    const puzzleArr = [
        {
            id: 0,
            //图片名称 这里取名就是对应了加载模块的
            name: 'puzzle_item01.png',
            // 初始化碎片一开始的定位
            x: 620,
            y: 470,
          	//是否已经在正确位置 
            correct: false,
        },
        {
            id: 1,
            name: 'puzzle_item02.png',
            x: 660,
            y: 280,
            correct: false,
        },
        {
            id: 2,
            name: 'puzzle_item03.png',
            x: 980,
            y: 480,
            correct: false,
        },
        {
            id: 3,
            name: 'puzzle_item04.png',
            x: 960,
            y: 300,
            correct: false,
        },


    ]
    // 定义正确的位置
    const correctPosition = [
        {
            x2: 812,
            y2: 284
        },
        {
            x2: 864,
            y2: 458
        },
        {
            x2: 760,
            y2: 460
        },
        {
            x2: 811,
            y2: 572
        },
    ]
    // app容器
    let content = app.value.stage;
  	//当前选择的精灵 
    let dragTarget = null;
    // 拖动到正确位置的差值(越大范围越大就是不需要贴得那么贴合就自动判断为正确)
    let correctRange = 25;
    // 当前的下标
    let currentIndex;

    // 创建一个拼图的容器
    const puzzleContainer: any = new PIXI.Container();
    // 开启事件功能
    puzzleContainer.interactive = true;
    puzzleContainer.eventMode = 'static';
    // 添加到主父容器
    content.addChild(puzzleContainer)
    // 添加完整的拼图样子展示在页面
    let contentSprite = new PIXI.Sprite(textureList['puzzle_content.png']);
    // 设置中心点
    contentSprite.anchor.set(0.5);
    // 居中显示
    contentSprite.position.set(app.value.screen.width / 2, app.value.screen.height / 2);
  	// 添加到拼图容器里
    puzzleContainer.addChild(contentSprite)

    // 循环创建碎片精灵
    for (let i = 0; i < puzzleArr.length; i++) {
        createPuzzle(puzzleArr[i])
    }


    // 创建精灵
    function createPuzzle(item) {
        let { id, name, x, y } = item
        // 创建碎片精灵。                     这里用到的textlist 在上面已经做过解释啦
        const puzzle: any = new PIXI.Sprite(textureList[name]);
        // 提前设置好定位
        puzzle.position.set(x, y);
        puzzle.anchor.set(0.5);
        puzzle.eventMode = "static";
        puzzle.interactive = true;
        // 添加按下事件
        puzzle.on("pointerdown", onPuzzleDown, puzzle)
        puzzle['puzzleIndex'] = id
        puzzleContainer.addChild(puzzle);
    }
    // 当前选择的第几个的下标
    function onPuzzleDown(e) {
      
        currentIndex = this.puzzleIndex;
        // 把当前选择的定义给赋值出去
        dragTarget = this;
        // 这里让层级在最上面
        puzzleContainer.setChildIndex(this, puzzleContainer.children.length - 1)
        puzzleContainer.on("pointermove", onPuzzleMove);
    }

  	// 鼠标移动函数
    function onPuzzleMove(e) {
        if (dragTarget) {
            // console.log('移动看看e.data.global', e.data.global);
            dragTarget.parent.toLocal(e.data.global, null, dragTarget.position);
        }

    }
    // 鼠标按键松开函数
    function onPuzzleUp(e) {
        if (dragTarget) {
            console.log('看看起来的定位', dragTarget.position);
            let { x, y } = dragTarget.position;
            let { x2, y2 } = correctPosition[currentIndex];
            // 相差正负12以内
            if (x > x2 - correctRange && x < x2 + correctRange && y > y2 - correctRange && y < y2 + correctRange) {
                dragTarget.position.set(x2, y2)
                puzzleArr[currentIndex].correct = true;
              	// 对精灵是否在正确位置进行修改
                let identifyArr = puzzleArr.map(item => {
                    return item.correct === true
                })
                // 数组判断找不到false说明全部拼到正确位置啦
                if (identifyArr.indexOf(false) === -1) {
                    // 执行相关拼图逻辑
                    puzzleSuccess()
                }
            } else {
                // let { x, y } = puzzleArr[currentIndex];
                // 回到原位
                // dragTarget.position.set(x, y);
                // 状态重新改为false
                puzzleArr[currentIndex].correct = false;
            }
            puzzleContainer.off('pointermove', onPuzzleMove);
            dragTarget = null;
        }

    }

    function puzzleSuccess () {
        console.log('拼图成功呀--执行逻辑');
        // 这里可以执行拼图成功后的相关逻辑
        
    }

    puzzleContainer.on('pointerup', onPuzzleUp);
    puzzleContainer.on('pointerupoutside', onPuzzleUp);


}

 如果有不懂可以问我,亦或者下期出加载的相关逻辑代码和有什么优点

(此demo是一年前学习pixi的时候写的,如有不足请谅解)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林漆呢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值