【cocos creator】2.x,伪3d拖拽,45度视角,60度视角,房屋装扮

伪3d拖拽,45度视角,60度视角
工程下载:(待审核)
https://download.csdn.net/download/K86338236/89530812

在这里插入图片描述

dragItem2.t s


import mapCreat2 from "./mapCreat2";


const { ccclass, property } = cc._decorator;
/**
 * 拖拽类,挂在要拖拽的节点上
 */
@ccclass
export default class dragItem2 extends cc.Component {

    @property(mapCreat2)
    mapCreat: mapCreat2 = null;

    private _originPos: cc.Vec2;
    private _startPos: any;
    oginPos: any;

    colRowPos = cc.v3(0, 0, 0)

    onLoad() {
        this.oginPos = this.node.position;
        this.regiestNodeEvent(this.node.children[0] || this.node);
    }

    init(pos) {
        this.colRowPos = pos;
    }

    /** 节点注册事件 */
    regiestNodeEvent(node: cc.Node) {
        if (!node) return;
        node.on(cc.Node.EventType.TOUCH_START, this.touchStartEvent, this);
        node.on(cc.Node.EventType.TOUCH_MOVE, this.touchMoveEvent, this);
        node.on(cc.Node.EventType.TOUCH_END, this.touchEndEvent, this);
        node.on(cc.Node.EventType.TOUCH_CANCEL, this.touchEndEvent, this);
    }

    touchStartEvent(event) {
        console.log('touch start--------')
        this._originPos = this.node.getPosition();
        this._startPos = event.getLocation();
        this.node.zIndex = 9999;
        this.mapCreat.removeBox(this.colRowPos)
    }

    touchMoveEvent(event) {
        let pos = event.getLocation();
        if (!this._startPos) {
            return;
        }
        let offset_x = pos.x - this._startPos.x;
        let offset_y = pos.y - this._startPos.y;

        this.node.x = this._originPos.x + offset_x;
        this.node.y = this._originPos.y + offset_y;
    }

    touchEndEvent(event) {
        this._startPos = null;
        this.setPos(false)
    }


    setPos(isInit?) {
        const { endPos, col, row, layer } = this.mapCreat.getPutPos(this.node, isInit, this.colRowPos)
        if (!endPos) return
        this.node.position = endPos;
        this.colRowPos = cc.v3(col, row, layer);
        this.mapCreat.addBox(cc.v3(col, row, layer))
        this.node.zIndex = -col * 10 - row * 10 + layer;
    }
}


mapCreat2.ts

import dragItem from "./dragItem";


const { ccclass, property } = cc._decorator;

@ccclass
export default class mapCreat extends cc.Component {

    //可修改

    mapH = 10;     // 地图纵向格子数量
    mapW = 10;     // 地图横向格子数量

    _layerH = 64.3;     // 地图单元格子高度,根据ui素材调整
    _gridW = 64.3;   // 地图单元格子长度,根据ui素材调整
    _gridH = 19;   // 地图单元格子宽度,根据ui素材调整
    boxAngel = 52;//地图伪3d角度,根据ui素材调整


    @property(cc.Graphics)
    map: cc.Graphics = null;
    @property(cc.Node)
    boxRoot: cc.Node = null;
    @property(cc.Node)
    boxNode: cc.Node = null;


    maxLayer = 0;   //最大高度
    gridsList = null


    onLoad() {
        this.gridsList = null;
        this.maxLayer = 0;
        this.initMap();
    }

    protected start(): void {
        let boxArr = ["1,1|1,2|1,3|2,1|2,2|3,1", "1,1|1,2|2,1", "1,1"]
        //行列不超过mapW,mapH
        this.init(boxArr)
    }

    init(boxArr) {
        this.creatSceneBox(boxArr)
    }

    /**
     * 初始化格子二维数组
     */
    initMap() {
        this.gridsList = new Array(this.mapW);
        for (let col = 0; col < this.gridsList.length; col++) {
            this.gridsList[col] = new Array(this.mapH);
        }

        this.map.clear();
        for (let col = 0; col < this.mapW; col++) {
            for (let row = 0; row < this.mapH; row++) {
                this.addGrid(col, row, 0);
            }
        }
        this.drawBlock()
    }

    addGrid(x, y, topLayer) {
        let grid = {
            x: 0,
            y: 0,
            zArr: [0],
            topLayer: 0
        }
        grid.x = x;
        grid.y = y;
        grid.topLayer = topLayer;
        this.gridsList[x][y] = grid;
    }

    /**
     * 绘制底部地图线
     */
    drawBlock() {
        for (let col = 0; col <= this.mapW; col++) {
            this.drawLine(cc.v2(col - 0.5, -0.5), cc.v2(col - 0.5, this.mapH - 0.5));
        }
        for (let row = 0; row <= this.mapH; row++) {
            this.drawLine(cc.v2(0 - 0.5, row - 0.5), cc.v2(this.mapW - 0.5, row - 0.5));
        }
    }

    creatSceneBox(boxArr = []) {
        let maxData = this.getMaxWidth(boxArr)
        this.boxRoot.children.forEach((value) => { value.active = false })
        let index = 0;
        for (let i = 0; i < boxArr.length; i++) {
            const element = boxArr[i];
            index = this.creatBox(element, this.boxRoot, i, index, maxData);
        }
    }

    /**
     * 获取方块位置范围
     * @param boxArr 
     * @returns 
     */
    getMaxWidth(boxArr) {
        let minX = 999
        let maxX = -999
        let minZ = 999
        let maxZ = -999
        for (let i = 0; i < boxArr.length; i++) {
            const element1 = boxArr[i];
            const element = element1.split("|")
            for (let j = 0; j < element.length; j++) {
                const element2 = element[j];
                let pos = element2.split(",")
                let x = (Number(pos[0]) - 1) || 0
                let z = (Number(pos[1]) - 1) || 0
                if (x < minX) minX = x
                if (x > maxX) maxX = x
                if (z < minZ) minZ = z
                if (z > maxZ) maxZ = z
            }
        }
        let middleX = Math.floor((maxX - minX) / 2);
        let middleY = Math.floor((maxX - minX) / 2);
        let maxData = { minX, maxX, minZ, maxZ, middleX, middleY }
        return maxData;
    }

    /**
     * 创建方块初始位置
     * @param boxString 
     * @param parent 
     * @param layer 
     * @param index 
     * @param maxData 
     * @returns 
     */
    creatBox(boxString = "", parent: cc.Node, layer, index, maxData) {
        let boxArr = boxString.split("|")
        for (let i = 0; i < boxArr.length; i++) {
            const element = boxArr[i];
            let colRowPos = element.split(",")
            let x = Number(colRowPos[0]) - 1 + Math.floor(this.mapW / 2) - maxData.middleX
            let y = this.mapH - (Number(colRowPos[1]) + Math.floor(this.mapH / 2)) - maxData.middleY
            let box = parent.children[index] || cc.instantiate(this.boxNode)
            box.parent = parent;
            let newPos = cc.v3(x, y, layer)
            let pos = this.getPos(newPos)
            box.name = `box${pos[0]}_${pos[i]}_layer`
            box.setPosition(pos)
            box.zIndex = x * 10 - y * 100 + layer;
            box.active = true
            box.getComponent(dragItem).init(newPos)
            this.addBox(newPos)
            index++
        }
        return index;
    }

    /**
     * 添加方块到地图数组
     * @param newPos 
     * @returns 
     */
    addBox(newPos) {
        const { x, y, z } = newPos;
        if (!this.gridsList[x] || !this.gridsList[x][y]) return
        let zArr = this.gridsList[x][y].zArr;
        if (zArr[z]) return;
        zArr[z] = 1
        if (!zArr[z + 1]) zArr[z + 1] = 0
        if (z + 1 > this.maxLayer) this.maxLayer = z + 1;
        this.logMap()
    }

    /**
     * 从地图数组移除方块
     * @param newPos 
     * @returns 
     */
    removeBox(newPos) {
        const { x, y } = newPos;
        if (!this.gridsList[x] || !this.gridsList[x][y]) return
        let zArr = this.gridsList[x][y].zArr
        zArr[newPos.z] = 0;
        let newArr = []

        for (let i = zArr.length - 1; i >= 0; i--) {
            const element = zArr[i];
            if (!newArr.length && !element) continue;
            if (!newArr.length && element) {
                newArr.unshift(0)
            }
            newArr.unshift(element || 0)
        }
        if (!newArr.length) {
            newArr.unshift(0)
        }
        this.gridsList[x][y].zArr = newArr
        this.gridsList[x][y].topLayer = newArr.length
        if (newArr.length > this.maxLayer) this.maxLayer = newArr.length;
        this.logMap()
    }

    /**
     * 打印当前方块数组
     */
    logMap() {
        let str = ""
        for (let row = this.mapH - 1; row >= 0; row--) {
            for (let col = 0; col < this.mapW; col++) {
                for (let i = 0; i <= this.maxLayer; i++) {
                    let box = this.gridsList[col][row].zArr[i] || "0"
                    str += box
                }
                str += " "
            }
            str += ("\n")
        }
        // cc.log(str)
    }

    /**
     * 获取当前位置周围是否有方块
     * @param pos 
     * @returns 
     */
    getSideBox(pos) {
        const { x, y, z } = pos
        if (!this.gridsList[x] || !this.gridsList[y]) return false
        let zArr = this.gridsList[x][y].zArr
        if (zArr[z - 1] || zArr[z + 1]) return true
        let chsecArr = [{ x: 0, y: 1 }, { x: 0, y: -1 }, { x: -1, y: 0 }, { x: 1, y: 0 }]
        let canput = false
        for (let index = 0; index < chsecArr.length; index++) {
            const element = chsecArr[index];
            if (!this.gridsList[x + element.x] || !this.gridsList[x + element.x][y + element.y]) {
                continue;
            }
            let zArr = this.gridsList[x + element.x][y + element.y].zArr
            if (zArr[z]) {
                canput = true;
                break;
            }
        }
        return canput;
    }

    /**
     * 根据方块位置,获取需要放置到的位置
     * @param node 
     * @param isInit 
     * @param colRowPos 
     * @returns 
     */
    getPutPos(node, isInit = true, colRowPos) {
        let worldPos = node.convertToWorldSpaceAR(cc.v2(0, 0));
        let boxPos = this.node.convertToNodeSpaceAR(worldPos);
        let minDis = 9999;
        let endPos = boxPos;
        let endRow = colRowPos.y;
        let endCol = colRowPos.x;
        let layer = colRowPos.z;
        for (let col = 0; col < this.mapW; col++) {
            for (let row = 0; row < this.mapH; row++) {

                let data = this.gridsList[col][row]
                let have = false
                for (let i = 0; i <= this.maxLayer; i++) {
                    const element = data.zArr[i];
                    if (element) have = true
                }
                for (let i = 0; i <= this.maxLayer; i++) {
                    const element = data.zArr[i];
                    if (element) continue;
                    if (!isInit && i > 0) {
                        let canPut = this.getSideBox(cc.v3(col, row, i))
                        if (!canPut) continue;
                    }
                    let pos = this.getPos(cc.v3(col, row, i));
                    let distance = pos.sub(boxPos).mag()
                    if (!endPos || distance < minDis) {
                        minDis = distance;
                        endPos = pos;
                        endRow = row;
                        endCol = col;
                        layer = i;
                    }
                }
            }
        }
        return { endPos, col: endCol, row: endRow, layer }
    }

    /**
     * 根据方块格子下标获取2d坐标
     * @param pos 方块格子位置 cc.v3(x:列,y:行,z:第几层,最下层为0)
     * @returns 位置position
     */
    getPos(pos) {
        const { x, y, z } = pos
        let radian = (Math.PI / 180 * (this.boxAngel));
        let posX = (x - this.mapW / 2) * (this._gridW) + y * this._gridH * Math.tan(radian);
        let posY = (y - this.mapH / 2) * (this._gridH) + z * this._layerH;
        return cc.v3(posX, posY)
    }

    /**
     * 画线
     * @param start_col_cow 
     * @param end_col_cow 
     * @param color 
     * @param width 
     */
    drawLine(start_col_cow, end_col_cow, color = cc.Color.GRAY, width = 2) {
        this.map.strokeColor = color;
        this.map.strokeColor.a = 80;//添加透明度
        let pos1 = this.getPos(start_col_cow)
        let pos2 = this.getPos(end_col_cow)
        this.map.lineWidth = width;
        this.map.moveTo(pos1.x, pos1.y);
        this.map.lineTo(pos2.x, pos2.y);
        this.map.stroke();
    }

    /**
     * 画点
     * @param col 
     * @param row 
     * @param color 
     */
    drawPoint(col, row, color = new cc.Color().fromHEX("#FF000033")) {
        this.map.fillColor = color;
        this.map.fillColor.a = 20;//添加透明度
        let pos = this.getPos(cc.v2(col, row))
        this.map.fillRect(pos.x, pos.y, 10, 10);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

烧仙草奶茶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值