Laya 关卡地图缩放

简单的样子 如上图所示

先理清思路,确定设计需求

设想一下,关卡地图有背景图,N多个关卡,如果每个关卡设计成节点,添加再关卡图上,这样拖动和缩放就比较好解决,所以整理后有3个需求

1.关卡地图拖动

2.关卡地图缩放

3.点击关卡,被点击的关卡居中显示

解决关卡地图的拖动

拖动的效果,首先是手指往哪个方向滑动,地图就往哪边移动。例如手指向上滑动,就向上移动。然后移动到一定的位置后,达到边界,不能再移动。整个逻辑和打飞机游戏,控制飞机的移动一样。背景图累加,触控点的差值。

       /**
         * 地图拖动
         */
        private mapDrag(): void {
            let mapX = this._mapPoint.x
            let mapY = this._mapPoint.y
            let posX = mapX + (Laya.stage.mouseX - this._lastMouseDown.x)
            let posY = mapY + (Laya.stage.mouseY - this._lastMouseDown.y)

            let isXMove: boolean = true
            let isYMove: boolean = true
            // 地图超过边界,并且移动方向和地图通向时 限制移动
            if (posX < this._leftBorder && posX <= mapX) { isXMove = false }
            if (posX > this._rightBorder && posX >= mapX) { isXMove = false }
            if (posY < this._topBorder && posY <= mapY) { isYMove = false }
            if (posY > this._bottomBorder && posY >= mapY) { isYMove = false }

            if (isXMove) { this._mapPoint.x = posX }
            if (isYMove) { this._mapPoint.y = posY }

            this._lastMouseDown.x = Laya.stage.mouseX
            this._lastMouseDown.y = Laya.stage.mouseY
            this.updateImgPos()
        }

 

/**

* 更新图片位置

*/

private updateImgPos(): void {

let point = new Laya.Point(this._mapPoint.x, this._mapPoint.y)

this.globalToLocal(point, false)

this.imgView.x = point.x

this.imgView.y = point.y

}

这里的重置图片位置,先转换成了屏幕坐标,因为触控点是stage上的位置,所以都用stage的坐标系。图片的位置是(0,0),锚点也是(0,0)。这样计算位置时,就比较方便,虽然是stage的子节点,但是起始点都是一样,在实际效果中就不会有误差

UI像这样

解决关卡地图的缩放

这个缩放参考了大佬的博客,很强大,感谢大佬的分享

https://blog.csdn.net/winnershili/article/details/80093017

http://bl.ocks.org/sgruhier/1d692762f8328a2c9957

 

主要实现了以鼠标点为中心,控制缩放。通过调整位置 和缩放值,达到聚焦缩放的效果。然后在改成触摸屏幕缩放时,发现如果第一次触摸,就是刚把手指放上去时,就调整了位置,这样实际效果看起来不是很平滑。还有就是缩放后,关卡地图的大小变了,这样边界也需要调一下

1.初次触摸,不改变

2.调整边界的位置

/**

* 鼠标移动

*/

private onMouseMove(e: Laya.Event): void {

if (!this._isMouseDown) { return }

if (e.touches && e.touches.length >= 2) {

this.touchScaleMap(e.touches)

return

}

this.mapDrag()

}

 

/**

* 鼠标抬起

*/

private onMouseUp(e: Laya.Event): void {

this._isMouseDown = false

this._lastDistance = 0

}

 

/**

* 鼠标按下

*/

private onMouseDown(): void {

this._isMouseDown = true

this._lastMouseDown.x = Laya.stage.mouseX

this._lastMouseDown.y = Laya.stage.mouseY

 

}

 

/**

* 触控缩放

*/

private touchScaleMap(points: Array<any>): void {

//计算中心点

this._scaleCenter.x = (points[0].stageX + points[1].stageX) * 0.5

this._scaleCenter.y = (points[0].stageY + points[1].stageY) * 0.5

 

//计算缩放值

let distance: number = this.getDistance(points);

let changeValue = (distance - this._lastDistance) * this._scaleSmoothness

let isFirst = false

if (this._lastDistance == 0) { isFirst = true }

this._lastDistance = distance

if (isFirst) { return }

this.changeScale(changeValue)

}

 

/**

* 改变缩放值

*/

private changeScale(changeValue): void {

this._currentScale += changeValue

if (this._currentScale > 2) {

this._currentScale = 2

}

if (this._currentScale < 0.3) {

this._currentScale = 0.3

}

this.mapScale()

}

 

/**

* 地图缩放

*/

private mapScale(): void {

let mapX = this._mapPoint.x

let mapY = this._mapPoint.y

let disX = this._scaleCenter.x - mapX

let disY = this._scaleCenter.y - mapY

let scareRateDis = (this._currentScale - this._lastScale) / this._lastScale

this._mapPoint.x = mapX - disX * scareRateDis

this._mapPoint.y = mapY - disY * scareRateDis

this._lastScale = this._currentScale

this.updateImgPos()

this.updateImageScale()

this.setBorder()

}

 

这里自适应为了在手机中图片看起来不花,设置的浏览器宽高,自定义调整缩放,如果不是这样的,UIUtil.scale不要就可以了

/**

* 构造函数

*/

    constructor() {

        //TS或JS版本初始化微信小游戏的适配

        Laya.MiniAdpter.init();

        Laya.MiniAdpter['getUrlEncode'] = Main.getUrlAndEncode;

        Laya.init(Laya.Browser.width, Laya.Browser.height, laya.webgl.WebGL);

        Laya.stage.frameRate = Laya.Stage.FRAME_FAST;

        Laya.stage.scaleMode = Laya.Stage.SCALE_NOSCALE;

        UIConfig.closeDialogOnSide = false;

        Main.startLoad()

    }

/**

* 设置边界

*/

private setBorder(): void {

this.boxMask.visible = false

let borderDis = 100 * UIUtil.scale

// 图片在手机中的宽高 自适应+缩放

let imgWidthInPhone = this.imgView.width * UIUtil.scale * this._currentScale

let imgHeightInPhone = this.imgView.height * UIUtil.scale * this._currentScale

// 屏幕的真是宽高

let screenWidth = Laya.Browser.width

let screenHeight = Laya.Browser.height

 

//设置边界

this._leftBorder = -imgWidthInPhone - borderDis + screenWidth

this._rightBorder = borderDis

this._topBorder = -imgHeightInPhone - borderDis + screenHeight

this._bottomBorder = borderDis

}

 

解决点击关卡,关卡位置居中

想法是,计算关卡位置 和屏幕中心位置 之间的差值,然后用tween 动画移动,为什么用tween动画,是为了让它平滑移动,看起来不会突然。然后这个关卡是添加在背景图上的,所以要转换成stage坐标。因为用来自定义缩放做手机适配,这里直接用localToGlobal转换的坐标,有误差,本来不会有的。自定义缩放适配,是在添加到stage的时候,根据屏幕高宽和设计时的高宽比,调整缩放,那么它的字节点坐标,和直接添加在stage上比,就是被缩放过的。所以这里自己计算一下,先获得和父节点同一个parent的坐标,,关卡的坐标*缩放值+父节点坐标=在父节点parent的坐标,把这个坐标转成世界坐标。

1.平滑过度

2.计算关卡位置和屏幕中心的位置

3.tween动画时,不能触摸

/**

* 关卡节点点击

*/

private onLevelNodeClick(point: Laya.Point): void {

point.x *= this._currentScale

point.y *= this._currentScale

point.x += this.imgView.x

point.y += this.imgView.y

this.localToGlobal(point, false)

let mapX = this._mapPoint.x

let mapY = this._mapPoint.y

this._lastMouseDown.x = point.x

this._lastMouseDown.y = point.y

let posX = mapX + (Laya.stage.width * 0.5 - this._lastMouseDown.x)

let posY = mapY + (Laya.stage.height * 0.5 - this._lastMouseDown.y)

this._lastMouseDown.x = point.x

this._lastMouseDown.y = point.y

let ease = Laya.Ease.linearNone

let updateFunc: Laya.Handler = new Laya.Handler(this, this.updateImgPos)

this.boxMask.visible = true

let compeleteFunc: Laya.Handler = Laya.Handler.create(this, this.onLevelNodeClickOver)

Laya.Tween.to(this._mapPoint, { x: posX, y: posY, update: updateFunc }, 300, ease, compeleteFunc, 0, true, true)

}

在UI上添加的boxMask就是为了不让触摸。下面是自定义适配

/**

* 添加到舞台

* @param ui

*/

public static addToStage(ui: Laya.Sprite): void {

if (null == ui) {

return;

}

if (0 == this._scale) {

this._scale = Laya.Browser.width / GameConfig.width;

}

 

ui.scale(this._scale, this._scale);

Laya.stage.addChild(ui);

}

 

/**

* 缩放比例

*/

public static get scale(): number {

if (0 == this._scale) {

return Laya.Browser.width / GameConfig.width;

}

return this._scale;

}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值