前言: 拖拽移动对象是2D休闲小游戏中常用的一个功能,典型代表例如《植物大战僵尸》中,种植植物的表现形式,拖拽植物卡片种植到相应的地点。今天介绍一下在Laya项目中实现这一功能。
该功能实现参照了 :Egret拖拽对象与吸附 https://blog.csdn.net/u013617851/article/details/83867180
思路: 在 Laya 中实现拖拽对象,需要用到MOUSE_MOVE事件的监听,触摸移动触发MOUSE_MOVE,此时计算触摸移动的大小,让拖拽对象也进行相应的移动。
演示:
开发:
- 首先创建一个页面,页面上摆放好目标格子。我这边摆了9个,编号分别是
panel_00 ~panel_08
。然后动态加载出来我们要拖拽的材料:
initUI() {
for (let i = 0; i < 3; i++) {
let pd: ProductItem = new ProductItem(false);
this.bottomGp.addChild(pd);
}
}
- 在拖拽开始的时候,在材料的位置实例化出来一个同样的材料对象,并且将坐标转化为世界坐标,并添加监听事件:
private curTargetObj: ProductItem;
private storeX: number; //拖拽对象的初始位置X
private storeY: number; //拖拽对象的初始位置Y
private PointX: number = 100; //吸附点坐标X
private PointY: number = 100; //吸附点坐标Y
public instantiatePro(obj: ProductItem, e) {
this.curTargetObj = new ProductItem(true);
this.curTargetObj.img_product.skin = obj.img_product.skin;
this.curTargetObj.x = obj.localToGlobal(new Laya.Point()).x;
this.curTargetObj.y = obj.localToGlobal(new Laya.Point()).y;
this.onMoveBegin(e);
this.initTargetObjBindEvent();
this.addChild(this.curTargetObj);
}
private initTargetObjBindEvent() {
this.curTargetObj.on(Laya.Event.MOUSE_MOVE, this, this.onMoving);
this.curTargetObj.on(Laya.Event.MOUSE_UP, this, this.onMoveEnd);
}
private XTouch: number;
private YTouch: number;
private onMoveBegin(e): void {
//Obj对象的坐标
this.storeX = this.curTargetObj.x;
this.storeY = this.curTargetObj.y;
//想办法记录鼠标移动的记录的坐标
this.XTouch = e.stageX;
this.YTouch = e.stageY;
}
- 在拖拽的过程中让实例化出来的对象跟随鼠标(手指)的移动而移动:
private onMoving(e): void {
this.curTargetObj.x = this.storeX + (e.stageX - this.XTouch);
this.curTargetObj.y = this.storeY + (e.stageY - this.YTouch);
}
- 当移动到适当的位置后松开鼠标(手指),对象会搜索最近的格子所在的位置,并以缓动动画的形式吸附过去,如果停止的位置距离目标区域差距过大,则回到起始的位置,并自动销毁。
private onMoveEnd(): void {
// 拖拽结束后,计算坐标
let self = this;
let closePoint: number = 0;//第几个point是最近的
let closelen: number = 1000;//设定个阈值
let zoneMin: number = 750;
let zoneMax: number = 1150;
let len: number = 0;
if (self.curTargetObj.y < zoneMin || self.curTargetObj.y > zoneMax) {
// 如果不满足吸附条件,就回到原来位置,并且销毁/
this.PointX = this.storeX;
this.PointY = this.storeY;
Laya.timer.once(400, this, () => {
this.curTargetObj.destroy();
});
} else {
// 吸附到最近的地方
for (let i: number = 0; i < 9; i++) {
//两个Obj距离公式
len = Math.sqrt(Math.pow((self["panel_0" + i].x - self.curTargetObj.x), 2) + Math.pow((self["panel_0" + i].y - self.curTargetObj.y), 2)); //Math.pow(2,4);表示2的4次方,等于16 ,Math.sqrt(x);
if (len < closelen) {
closelen = len;
closePoint = i;
}
}
this.PointX = this["panel_0" + closePoint].x + 50; // 相对于目前的模块居中
this.PointY = this["panel_0" + closePoint].y;
}
Laya.Tween.to(self.curTargetObj, { x: self.PointX, y: self.PointY }, 400, Laya.Ease.cubicOut);
}
这里计算距离的公式实际上就是求两点之间直线距离的公式:
最后送上整个项目的打包源码:
LayaAir拖拽移动对象并吸附源码