cocos2d-x 角色选择视图 类似ListView

本文介绍了一个游戏角色选择场景的实现,通过触摸操作控制角色在屏幕上的移动,并且设置了边界限制,确保角色只能在一定范围内移动。角色集合中会自动计算并跟随最近角色的移动。场景中包含了创建角色、监听触摸事件、处理触摸开始、移动和结束的动作,以及判断边界条件的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先来一张效果图:

1.左侧右侧都有边界 划到头会划不动

2.松手后总会有一个最近的向中心移动,其他的跟随移动


#ifndef __HEROSELECT_SCENE_H__
#define __HEROSELECT_SCENE_H__

#include "cocos2d.h"

class HeroSelect : public cocos2d::LayerColor
{
public:
    static cocos2d::Scene* createScene();
	CREATE_FUNC(HeroSelect);

private:
	virtual bool init();
	virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);
	virtual void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event);
	virtual void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event);
	virtual void onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_event);

	//边界检测 保证左右两侧各有滑动边界 
	bool isBoundary();

	//计算角色集合中 距离中心最近的角色与中心的距离
	float calcDistance();
public:

private:
	//用该节点作为所有商品的父节点 方便集体调整位置
	cocos2d::Node *view = nullptr;

	//开始触摸的坐标
	cocos2d::Vec2 touchBeginVec2;

	//角色集合 
	cocos2d::Vector herosVector;

	//角色集合中 距离中心最近的角色与中心的距离
	float distance;

};

#endif // __HEROSELECT_SCENE_H__#include "HeroSelect.h"

USING_NS_CC;

Scene* HeroSelect::createScene()
{
    auto scene = Scene::create();
    
	auto layer = HeroSelect::create();

    scene->addChild(layer);

    return scene;
}

bool HeroSelect::init()
{
	//白色背景
	if(!LayerColor::initWithColor(Color4B(255, 255, 255, 255)))
    {
        return false;
    }
    
    Size vSize = Director::getInstance()->getVisibleSize();

	view = Node::create();
	view->setPosition(vSize / 2);
	this->addChild(view);

	//创建所有角色
	for(int i = 1; i != 5; ++i)
	{
		std::string str = StringUtils::format("big_box%d.png", i);
		Sprite * sp = Sprite::create(str);
		sp->setPosition(Vec2((i - 1) * sp->getContentSize().width, 0));
		view->addChild(sp);

		herosVector.pushBack(sp);
	}
	
	auto listener = EventListenerTouchOneByOne::create();//创建一个触摸监听(单点触摸)  
	listener->onTouchBegan = CC_CALLBACK_2(HeroSelect::onTouchBegan, this);//指定触摸的回调函数  
	listener->onTouchMoved = CC_CALLBACK_2(HeroSelect::onTouchMoved, this);//指定触摸的回调函数  
	listener->onTouchEnded = CC_CALLBACK_2(HeroSelect::onTouchEnded, this);//指定触摸的回调函数  
	listener->onTouchCancelled = CC_CALLBACK_2(HeroSelect::onTouchCancelled, this);//指定触摸的回调函数  
	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    
    return true;
}

bool HeroSelect::onTouchBegan(Touch *touch, Event *event)
{
	touchBeginVec2 = touch->getLocation();
	return true;
}

void HeroSelect::onTouchMoved(Touch *touch, Event *unused_event)
{
	if(isBoundary())
	{
		return;
	}

	int moveX = touch->getLocation().x - touchBeginVec2.x;
	auto moveBy = MoveBy::create(0.0f, Vec2(moveX, 0));
	view->runAction(moveBy);

	touchBeginVec2 = touch->getLocation();
}

void HeroSelect::onTouchEnded(Touch *touch, Event *unused_event)
{
	view->stopAllActions();

	auto moveBy = MoveBy::create(0.2f, Vec2(calcDistance(), 0));
	view->runAction(moveBy);
}

void HeroSelect::onTouchCancelled(Touch *touch, Event *unused_event)
{
	onTouchEnded(touch, unused_event);
}

bool HeroSelect::isBoundary()
{
	Size vSize = Director::getInstance()->getVisibleSize();

	auto begin = herosVector.at(0);
	auto end = herosVector.at(herosVector.size() - 1);

	//讲在view节点上的相对坐标转换为VisibleSize的坐标(世界坐标)
	Vec2 left = begin->convertToWorldSpace(Vec2(begin->getContentSize().width / 2, 0));
	Vec2 right = end->convertToWorldSpace(Vec2(end->getContentSize().width / 2, 0));

	if(left.x > vSize.width / 2)
	{
		return true;
	}
	else if(right.x < vSize.width / 2)
	{
		return true;
	}

	return false;
}

float HeroSelect::calcDistance()
{
	float result = 1000.0f;
	Size vSize = Director::getInstance()->getVisibleSize();

	for(auto hero : herosVector)
	{
		Point p2world = hero->convertToWorldSpace(Point(0, 0)) + Vec2(hero->getContentSize().width / 2, 0);

		float dis = vSize.width / 2 - p2world.x;
		float temp = fabs(dis);

		if(temp < result)
		{
			result = dis;
		}
	}

	return result;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值