伪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);
}
}