Cocos Creator组件化开发之

您所在的位置:网站首页 地图的放大缩小功能怎么实现 Cocos Creator组件化开发之

Cocos Creator组件化开发之

2024-07-15 11:26| 来源: 网络整理| 查看: 265

“好记性不如烂笔头,记录开发过程中的点点滴滴”——xshu

“书写是对思维的缓存” ——佚名

进入正题

       在游戏开发过程中经常会遇到渲染元素的尺寸大于你所能展示的区域,需要玩家自行进行操作、拖动以及点击,比如地图通常会超出玩家所示区域,这个时候需要一个能够缩放、拖动以及点击的组件来完成这个需求。

  1.效果展示

        先来看看实际效果(由于电脑无法操作双指缩放,所以是先在手机上录屏然后再在电脑上做成gif的,文末有demo地址,大家可以下载下来自行体验一下)

  2.属性配置

      1.组件的一些配置参数,可以直接在编辑器里面填写数值来调试效果。

       2.再来看看组件的节点以及属性定义块

      下图是编辑器里面的设置

    3.在start生命周期接口里面会先对map和mapContainer进行判断,如果为空则取默认值。

  3.代码逻辑的实现细节 private addEvent(): void { this.map.on(cc.Node.EventType.TOUCH_MOVE, (event: any) => { if (this.operLock) return; // 如果触摸操作暂时锁定则不响应 let touches: any[] = event['getTouches'](); // 获取所有触摸点 // 1.x当多点触摸的时候 第二个触摸点即使不在node上也能进来 而且target也是当前node // 通过rect是否包含当前触摸点来过滤无效的触摸点 touches .filter(v => { let startPos: cc.Vec2 = v.getStartLocation(); // 触摸点最初的位置 let worldPos: cc.Vec2 = this.mapContainer.convertToWorldSpaceAR(cc.Vec2.ZERO); let worldRect: cc.Rect = cc.rect( worldPos.x - this.mapContainer.width / 2, worldPos.y - this.mapContainer.height / 2, this.mapContainer.width, this.mapContainer.height ); return worldRect.contains(startPos); }) .forEach(v => { // 将有效的触摸点放在容器里自行管理 let temp: any[] = this.mapTouchList.filter(v1 => v1.id === v.getID()); if (temp.length === 0) { this.mapTouchList.push({ id: v.getID(), touch: v }); } }) ; if (this.mapTouchList.length >= 2) { // 如果容器内触摸点数量超过1则为多点触摸,此处暂时不处理三点及以上的触摸点,可以根据需求来处理 this.isMoving = true; this.dealTouchData(this.mapTouchList, this.map); } else if (this.mapTouchList.length === 1) { // sigle touch let touch: any = this.mapTouchList[0].touch; let startPos: cc.Vec2 = touch.getStartLocation(); let nowPos: cc.Vec2 = touch.getLocation(); // 有些设备单点过于灵敏,单点操作会触发TOUCH_MOVE回调,在这里作误差值判断 if ((Math.abs(nowPos.x - startPos.x) { if (this.operLock) return; if (this.mapTouchList.length < 2) { // 当容器中仅剩最后一个触摸点时讲移动flag还原 this.isMoving = false; }; this.removeTouchFromContent(event, this.mapTouchList); }, this); this.map.on(cc.Node.EventType.MOUSE_WHEEL, (event) => { if (this.operLock) return; cc.log('==== MOUSE WHEEL ==='); let location: any = event['getLocation'](); let worldPos: cc.Vec2 = cc.v2(location.x, location.y); let scrollDelta: number = event['getScrollY'](); let scale: number = (this.map.scale - (scrollDelta / 10000 * -1)); let target: cc.Node = this.map; let pos: cc.Vec2 = target.convertToNodeSpaceAR(worldPos); this.smoothOperate(target, pos, scale); }, this); } // 删除无用的触摸点 public removeTouchFromContent(event: any, content: any[]): void { let eventToucheIDs: number[] = event['getTouches']().map(v => v.getID()); for (let len = content.length, i = len - 1; i >= 0; --i) { if (eventToucheIDs.indexOf(content[i].id) > -1) content.splice(i, 1); // 删除触摸 } }

2.处理触摸过程中的缩放动作

private dealTouchData(touches: any[], target: cc.Node): void { let touch1: any = touches[0].touch; let touch2: any = touches[1].touch; let delta1: any = touch1.getDelta(); let delta2: any = touch2.getDelta(); let touchPoint1: cc.Vec2 = target.convertToNodeSpaceAR(touch1.getLocation()); let touchPoint2: cc.Vec2 = target.convertToNodeSpaceAR(touch2.getLocation()); let distance: cc.Vec2 = touchPoint1.sub(touchPoint2); let delta: cc.Vec2 = delta1.sub(cc.v2(delta2.x, delta2.y)); let scale: number = 1; if (Math.abs(distance.x) > Math.abs(distance.y)) { scale = (distance.x + delta.x) / distance.x * target.scaleX; } else { scale = (distance.y + delta.y) / distance.y * target.scaleY; } let pos: cc.Vec2 = touchPoint2.add(cc.v2(distance.x / 2, distance.y / 2)); this.smoothOperate(target, pos, scale); } private smoothOperate(target: cc.Node, pos: cc.Vec2, scale: number): void { let scX: number = scale; // 当前缩放值与原来缩放值之差 let disScale: number = scX - target.scaleX; // 当前点击的坐标与缩放值差像乘 let gapPos: cc.Vec2 = pos.scale(cc.v2(disScale, disScale)); // 当前node坐标位置减去点击 点击坐标和缩放值的值 let mapPos: cc.Vec2 = target.getPosition().sub(cc.v2(gapPos.x, gapPos.y)); // 放大缩小 if (!this.isOutRangeScale(scale)) { scale = (scale * 100 | 0) / 100; target.scale = scale; this.dealScalePos(mapPos, target); } // 更新 label 显示 scale = this.dealScaleRange(scale); this.scaleTime.string = `${scale * 100 | 0}%`; } // 处理地图边缘缩放,移动地图 private dealScalePos(pos: cc.Vec2, target: cc.Node): void { if (target.scale === 1) { pos = cc.Vec2.ZERO; } else { let worldPos: cc.Vec2 = this.node.convertToWorldSpaceAR(pos); let nodePos: cc.Vec2 = this.node.convertToNodeSpaceAR(worldPos); let edge: any = this.calculateEdge(target, this.node, nodePos); if (edge.left > 0) { pos.x -= edge.left; } if (edge.right > 0) { pos.x += edge.right; } if (edge.top > 0) { pos.y += edge.top; } if (edge.bottom > 0) { pos.y -= edge.bottom; } } target.position = pos; }

3.处理玩家拖拽地图的操作

private dealMove(dir: cc.Vec2, map: cc.Node, container: cc.Node): void { let worldPos: cc.Vec2 = map.convertToWorldSpaceAR(cc.Vec2.ZERO); let nodePos: cc.Vec2 = container.convertToNodeSpaceAR(worldPos); nodePos.x += dir.x; nodePos.y += dir.y; let edge: any = this.calculateEdge(map, container, nodePos); if (edge.lBorderDelta


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3