大佬教程收集整理的这篇文章主要介绍了基于Cocos2d-x的实现tilemap地图双指缩放,单指拖动,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我们使用TiledMap制作了一张简单的地图,并把它加入到了程序中,紧接着本章将实现地图的双指缩放和单指移动功能。
在Cocos2d-x 3.x 中,实现触摸响应的一般流程如下:
1、首先,在GameScene.h文件中声明成员函数。
@H_618_28@
1
2
|
void
onTouchesMoved(
:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-size:1em!important; min-height:inherit!important; color:rgb(0,cocos2d::Event *event);
|
2、在GameScene.cpp文件的init函数中创建并绑定触摸事件。
两者的主要区别在于它们加入到事件分发器中的优先级的差异。其中的使用 addEventListenerWithSceneGraphpriority 方法添加的事件监听器优先级固定为0;而使用 addEventListenerWithFixedPriority 方法添加的事件监听器的优先级则可以自己设置,但不可以设置为 0,因为这个是保留给 SceneGraphpriority使用的。
3、最后在GameScene.cpp文件中实现触摸回调函数
一旦玩家开始触碰屏幕,我们的程序就会开始调用相应的触摸事件处理函数来处理相应的逻辑,所以现在我们就可以来完成这部分的逻辑了。
实现中有以下几个需要注意的问题:
(上图中,背景图片的锚点在蓝点的位置,当我们想放大红圈所圈的那棵树时,如果只是简单的改变背景的放大倍率,那一定会出现上图的第二种情况(目标会向右上角偏移);但如果我们把背景的锚点和位置都设置到目标处,那就会像第三中情况一样,得到一个比较好的放大效果。)
掌握了这些注意事项以后,现在我们就可以开始具体的行动了。
首先,在GameScene.h中定义如下的变量:
Sprite* bgSprite;
Vec2 bgOrigin;
|
bgSprite是地图背景,需要缩放和移动的对象都是其子节点,这样我们就可以通过操作它来实现缩放和移动了。bgOrigin用于记录bgSprite的初始原点位置。
接着,我们跳转到GameScene.cpp的init()方法,修改之前添加地图背景的方法,同时初始化bgOrigin。如下代码所示:
this
->addChild(mapLayer,-1);
bgSprite->setAnchorPoint(Vec2::ZERO);
bgSprite->setPosition(Vec2::ZERO),
bgOrigin = Vec2(Vec2::ZERO);
treeSprite->setAnchorPoint(Vec2::ZERO);
treeSprite->setPosition(Vec2::ZERO),
treeSprite->setScale(2);
bgSprite->addChild(treeSprite,2);
@H_283_40@map->setPosition(Vec2::ZERO),
bgSprite->addChild(map,1);
|
因为对层而言,它相比于其他的节点来说,其锚点、位置、大小都不好控制,所以我们需要通过另外的节点(比如这里的bgSprite)来执行后面的缩放和移动等动作。
最后压轴来了,实现触摸事件的处理函数如下:
void
GameScene::onTouchesMoved(
const
std::vector<Touch*>& touches,Event *event)
// 得到当前两触摸点
// 计算两点之间得距离
// 计算两触摸点上一时刻之间得距离
// 两触摸点与原点的差向量,pointVec1和pointVec2是相对于bgSprite的位置
auto pointVec1 = point1 - bgOrigin;
auto pointVec2 = point2 - bgOrigin;
// 两触摸点的相对中点
auto relMidx = (pointVec1.x + pointVec2.X) / 2 ;
auto relMidy = (pointVec1.y + pointVec2.y) / 2 ;
// 计算bgSprite的锚点
auto anchorX = relMidx / bgSprite->getBoundingBox().size.width;
auto anchorY = relMidy / bgSprite->getBoundingBox().size.height;
// 相对屏幕的中点
auto absMidx = (point2.x + point1.X) / 2 ;
auto absMidy = (point2.y + point1.y) / 2 ;
// 缩放时,为了避免出现空白的区域,需要做以下的边界处理。
// 当bgSprite快要进入到屏幕时,修改bgSprite的位置(既absMidx和absMidy)。
if
( bgOrigin.x > 0)
absMidx -= bgOrigin.x;
}
if
( bgOrigin.x < -bgSprite->getBoundingBox().size.width + winSize.width )
absMidx += -bgSprite->getBoundingBox().size.width + winSize.width - bgOrigin.x;
}
if
( bgOrigin.y > 0 )
absMidy -= bgOrigin.y;
}
if
( bgOrigin.y < -bgSprite->getBoundingBox().size.height + winSize.height )
absMidy += -bgSprite->getBoundingBox().size.height + winSize.height - bgOrigin.y;
}
// 重设bgSprite锚点和位置
bgSprite->setAnchorPoint(Vec2(anchorX,anchorY));
bgSprite->setPosition(Vec2(absMidx,absMidy));
// 根据两触摸点前后的距离计算缩放倍率
// 控制缩放倍率在1~4倍之间,最小倍率不能太小,不让背景将不能填充满整个屏幕。
bgSprite->setScale(scalE);
// 更新原点位置
bgOrigin = Vec2(absMidx,absMidy) - Vec2(bgSprite->getBoundingBox().size.width * anchorX,bgSprite->getBoundingBox().size.height * anchorY) ;
}
// 单点时,touches中只有一个Touch对象,所以通过touches[0]就可以得到触摸对象
auto touch = touches[0];
// 计算滑动过程中的滑动增量
auto diff = touch->getDelta();
// 得到当前bgSprite的位置
auto currentPos = bgSprite->getPosition();
// 得到滑动后bgSprite应该所在的位置
auto pos = currentPos + diff;
// 得到此刻bgSprite的尺寸
auto bgSpriteCurrSize = bgSprite->getBoundingBox().size;
//边界控制,约束pos的位置
pos.x = MAX(pos.x,-bgSpriteCurrSize.width + winSize.width + bgSpriteCurrSize.width * bgSprite->getAnchorPoint().X);
pos.y = MAX(pos.y,-bgSpriteCurrSize.height + winSize.height + bgSpriteCurrSize.height * bgSprite->getAnchorPoint().y);
// 重设bgSprite位置
bgSprite->setPosition(pos);
// 更新原点位置
|| pos.x <= -bgSpriteCurrSize.width + winSize.width + bgSpriteCurrSize.width * bgSprite->getAnchorPoint().X)
diff.x = 0;
}
|| pos.y <= -bgSpriteCurrSize.height + winSize.height + bgSpriteCurrSize.height * bgSprite->getAnchorPoint().y)
diff.y = 0;
}
bgOrigin += diff;
}
}
|
以上就是onTouchesMoved函数的实现方法了,原理已在注释中解释清楚,所以我想理解起来已经不会很难。下面给出一张示意图帮助大家理解:
下图是缩放过程中刚好出现空白的区域时的图形示意图:
此时空白的区域的宽等于-bgSprite->getBoundingBox().size.width + winSize.width - bgOrigin.x
,所以我们把背景的位置向右移动-bgSprite->getBoundingBox().size.width + winSize.width - bgOrigin.x
个单位就可以避免这种情况的出现。
代码中有一点需要注意的是,在缩放过程中,bgSprite的尺寸不断变化的,所以计算起锚点或进行边界处理时,一定要用它缩放后的尺寸宽高来计算,而不能是它本身的宽高。 所以代码中计算bgSprite的尺寸我们用getBoundingBox函数来获得经过缩放和旋转之后的外框盒大小,而不用getContentSize函数来获得节点原始的大小。
iOS端多点触碰默认是关闭的,所以需要在AppController.mm 程序启动回调中启用多点触摸才可以,具体方法是在以下的函数段后加入[eaglView setMultipleTouchEnabled:YES];
如下所示:
总的来说,要想很好的实现这一功能不是容易的,以上就是我们实现了的一种方法,虽然细节上还有一些问题,也未在真机上测试,但还是希望能对大家的学习有所帮助。如果你有更好的方法实现,也可以提出来,大家一起进步学习。
以上是大佬教程为你收集整理的基于Cocos2d-x的实现tilemap地图双指缩放,单指拖动全部内容,希望文章能够帮你解决基于Cocos2d-x的实现tilemap地图双指缩放,单指拖动所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。