cocos2dx鼠标拖动与释放

最近在学习cocos2dx,发现原来2.0版本以前是没有鼠标监听器的,既然3.0版本有了,那刚好来学习一下。

通过鼠标监听器来实现,图像随鼠标的拖动而移动,如果鼠标释放的时候,图像没有位于正确的位置,那么图像就回归原处。


首先是加载图像什么的,就不用多说了。

	Size visibleSize = Director::getInstance()->getVisibleSize();

	auto whiteLayer = LayerColor::create(Color4B(255, 255, 255, 255));
	this->addChild(whiteLayer);

	auto rectangle1 = Sprite::create("rectangle.png");
	rectangle1->setAnchorPoint(Point(0, 0));
	rectangle1->setPosition(Point(visibleSize.width / 5, visibleSize.height / 2));
	this->addChild(rectangle1);

	auto rectangle2 = Sprite::create("rectangle.png");
	rectangle2->setAnchorPoint(Point(0, 0));
	rectangle2->setPosition(Point(visibleSize.width / 5 * 3, visibleSize.height / 2));
	this->addChild(rectangle2);

	auto fg = Sprite::create("font.png");
	fg->setAnchorPoint(Point(0, 0));
	fg->setPositionZ(1);
	rectangle1->addChild(fg);

接着是配置监听器,现在3.0版本采用的是创建监听器,并将监听器添加到事件分发器上就可以了。

事件监听器有以下几种:

  • 触摸事件 (EventListenerTouch)
  • 键盘响应事件 (EventListenerKeyboard)
  • 鼠标响应事件 (EventListenerMouse)
  • 自定义事件 (EventListenerCustom)
  • 加速记录事件 (EventListenerAcceleration)

_eventDispatcher的工作由三部分组成:

  • 事件分发器 EventDispatcher
  • 事件类型 EventTouch, EventKeyboard 等
  • 事件监听器 EventListenerTouch, EventListenerKeyboard 等
其中_eventDispatcher是Node的一个属性,可以通过Director::getInstance()->getEventDispatcher获得。

注册的时候有两种方法,一种是addEventListenerWithSceneGraphPriority,另一种是addEventListenerWithFixedPriority,其中addEventListenerWithSceneGraphPriority会自动释放,所以可以优先使用这种方法。


顺便说一下,现在C++11多了特性lambda表达式,也就是匿名函数。可以参考这篇关于lambda表达式的文章http://www.cnblogs.com/haippy/archive/2013/05/31/3111560.html。


第一,监听器的创建和鼠标移动函数的实现,由于鼠标坐标系跟GL坐标系不太一样,它是以左上角为原点,向右为X轴正方向的,但是却以向上为Y轴正方向的,也就是其实界面的Y点都是负数的,所以利用visibleSize.height + cursorY来转换成正值。

对了,还有converToNoSpace函数,它是将某个点转化成在某个坐标系中的点,在这里是指鼠标的点转化成以rectangle1初始点为原点的坐标系中的点,从而能获得正确鼠标加载图像位置。


另外,setAnchorPoiint函数是关于锚点的设置。其中参数是以比例计算的,范围在0~1之间。


锚点就是子对象在父对象中的初始位置,通俗来讲,就是说setPosition是放置图像的位置,那么子对象是以什么点开始放置的呢?其实就是你设置的锚点,举个栗子,就是说setAnchorPoint(Point(0, 0)),setPosition(Point(100, 100)),那么子对象就以子对象的左下角为开始点,放置在(100,100)处,如果是setAnchorPoint(Point(1, 1)), setPosition(Point(100,100)),那么子对象就以子对象的右上角为开始点,放置在(100,100)处。


	// Mouse listener configuration, in which getCursorX, the getCursorY function is to
	// the upper left corner as the origin, to the right is the X axis, Y axis down negative.
	auto _mouseListen = EventListenerMouse::create();
	// The mouse move function.
	_mouseListen->onMouseMove = [=](Event* event)
	{
		EventMouse* e = (EventMouse*)event;
		if (e->getMouseButton() == 0)
		{
			float cursorX = e->getCursorX();
			float cursorY = e->getCursorY();
			Vec2 actualPosition = rectangle1->convertToNodeSpace(Point(cursorX, visibleSize.height + cursorY));
			fg->setAnchorPoint(Point(0.5, 0.5));
			fg->setPosition(actualPosition);
		}
	};

第二,释放鼠标函数,是判断某点是否位于区域中,使用的办法是通过获取图像矩形大小,然后利用方法containsPoint解决。其中,为了实现当放置点位于区域内时候,正确放置图像,将rectangle2原点左边转化成在recatangle1坐标系中的。

	// The mouse release function.
	_mouseListen->onMouseUp = [=](Event* event)
	{
		EventMouse* e = (EventMouse*)event;
		float cursorX = e->getCursorX();
		float cursorY = e->getCursorY();

		Vec2 actualPositionInRectangle2 = rectangle2->convertToNodeSpace(Point(cursorX, visibleSize.height + cursorY));
		Size size = rectangle2->getContentSize();
		Rect rect = Rect(0, 0, size.width, size.height);

		if (rect.containsPoint(actualPositionInRectangle2))
		{
			// To convert origin coordinates of second image in the coordinates system 
			// of the first image.
			Vec2 convertPosition = rectangle1->convertToNodeSpace(rectangle2->getPosition());
			fg->setAnchorPoint(Point(0, 0));
			fg->setPosition(convertPosition);
		}
		else
		{
			fg->setAnchorPoint(Point(0, 0));
			fg->setPosition(Point(0, 0));
		}
	};

最后,就是注册监听器。

	auto _eventDispatcher = Director::getInstance()->getEventDispatcher();
	_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListen, fg);

截图:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值