[cocos2d-x教程之 Hero教你打灰机] 如何制作一个虚拟摇杆

本文详细介绍了如何使用cocos2d-x制作一个虚拟摇杆,包括图片准备、设计思路和代码实现,特别适合飞行射击游戏中的玩家操作控制。

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



一、 前言

         很多大型游戏里 都采用了虚拟摇杆 ,即 手触摸 屏幕 才出现 摇杆,一方面 使 玩家更易操作, 另一方面则是使得 游戏的视觉变得更加酷炫 。这一篇教程就告诉大家如何 完成制作 一个 虚拟摇杆。


二、 图片准备

         笔者 不太精通ps,也没有费时间去画图了。只用了两个简单的有填充色的 圆形作为 摇杆的组成部分。 小圆代表摇杆,大圆代表摇杆的底座。

           

三、 一些构想

       首先把这个摇杆定位为一个飞行射击游戏的摇杆。即摇杆需要实现 飞机主角的移动。

       所以,大体上这就是一个点击屏幕会出现的虚拟摇杆。但是,考虑到一般飞行射击游戏 的玩家惯用 左手进行飞行操作,所以我们把点击出现虚拟摇杆的触摸区域定在左边的一块矩形 区域 。 屏幕右边的区域 用于 点击屏幕触摸  发射 子弹等 功能性 道具使用。  

      这里又有一个问题。

      一个固定大小的虚拟摇杆 可能会 不能满足玩家的需要。 不少玩家在 操纵摇杆时 手指会超出摇杆的范围(这也是玩游戏的人之常情嘛,总不能 让别人 正激动的时候 就 不让别人 操纵的摇杆了吧 。)


四、代码实现

        想到这里我就先直接上代码了吧。。

#ifndef __YAOGAN_SCENE_H__
#define __YAOGAN_SCENE_H__

#include "cocos2d.h"

#include "SimpleAudioEngine.h"

using namespace cocos2d;

class Yaogan : public cocos2d::CCLayer
{
public:
	
	// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
	
	CCSprite* jianpan_back;
	CCSprite* jianpan;
	
	int press_type ;//0-still 1-up 2-down 3-left 4-right 
	
	float anchor_bx;
	float anchor_by;
	float anchor_x;
	float anchor_y;

	virtual bool init();  

	// there's no 'id' in cpp, so we recommand to return the exactly class pointer
	static cocos2d::CCScene* scene();

	// a selector callback
	
	//check whether the yaogan can be show according to its coordinate;
	bool check_Can_Be_Show(CCPoint point);
	int is_Still_Pressed(CCPoint point);
	void set_Yaogan_Place(CCPoint point);
	void set_inner_Yaogan_Place(CCPoint point);
	
	void menuCloseCallback(CCObject* pSender);

	void backgroundRoll(float);

	void backgroundRoll();

	void initWithJianpan();

	void ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
	void ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
	void ccTouchesMoved(CCSet *pTouches , CCEvent *pEvent);

	// implement the "static node()" method manually

	CREATE_FUNC(Yaogan);
	//计算出x、y方向的位移。
	float calculate_Move_X( float x );
	float calculate_Move_Y( float y );

	void controll_Plane();
};

#endif  // __YAOGAN_SCENE_H__

      下面来详细讲解一下  代码的实现。

       

       

bool Yaogan::init()
{
	//////////////////////////////
	// 1. super init first
	if ( !CCLayer::init() )
	{
		return false;
	}

    initWithJianpan();
	this->setTouchEnabled(true);
	return true;
}

void Yaogan::initWithJianpan(){

	CCSize size = CCDirector::sharedDirector()->getWinSize();

	jianpan = CCSprite::create("jianpan2.png");

	jianpan_back = CCSprite::create("jianpan.png");

	jianpan->setPosition(ccp(size.width/6,size.height/4));

	jianpan_back->setPosition(ccp(size.width/6,size.height/4));

	this->addChild(jianpan,2);

	this->addChild(jianpan_back,1);

	anchor_bx = anchor_x = size.width / 6;
	anchor_by = anchor_y = size.height / 4;

}


首先是ccscene的初始化,在调用父类的init 函数后 ,设置这个layer 可触摸。也调用initjianpan() 把 虚拟键盘。

initjianpan 这是把  大图和小图都加载到层中。(要记得 设置visibility 为false 哦)


void Yaogan::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent){

	

	CCTouch *touch = dynamic_cast<CCTouch*>( pTouches->anyObject() );

	float x = touch->getLocation().x;
	float y = touch->getLocation().y;

	CCLog("inner_touch %f %f",x,y);

	//判断是否展现摇杆
	if(check_Can_Be_Show(ccp(touch->getLocation().x,touch->getLocation().y))){
		
		this->setVisible(true);
		set_Yaogan_Place(ccp(touch->getLocation().x,touch->getLocation().y));
	}

	//````

}

void Yaogan::ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent){
	this->setVisible(false);
}

void Yaogan::ccTouchesMoved(CCSet *pTouches , CCEvent *pEvent){

	if( this->isVisible() ){

		CCTouch*  touch = dynamic_cast<CCTouch*>( pTouches->anyObject() );

		int press_rs = is_Still_Pressed(ccp(touch->getLocation().x,touch->getLocation().y)) ;

		if( press_rs == 1 ){

			
			
			this->set_inner_Yaogan_Place(ccp(touch->getLocation().x,touch->getLocation().y));

		}else if( press_rs == 2 ){
			float x,y;

			x = y = 0.0f;

			 if(touch->getLocation().y == anchor_by){
				 y = anchor_by;
				 if( touch->getLocation().x > anchor_bx ){
					 x = anchor_bx + jianpan_back->getContentSize().width / 2 - jianpan->getContentSize().width / 2;
				 }else{
					 x = anchor_bx - jianpan->getContentSize().width / 2 + jianpan->getContentSize().width / 2;
				 }
			 }else if(touch->getLocation().x == anchor_bx){
				 x = anchor_bx;
				 if( touch->getLocation().y > anchor_by ){
					 y = anchor_bx + jianpan_back->getContentSize().height / 2 - jianpan->getContentSize().height / 2;
				 }else{
					 y = anchor_bx - jianpan->getContentSize().height / 2 + jianpan->getContentSize().height / 2;
				 }

			 }else{

			  float k = ( touch->getLocation().y - anchor_by ) /
			       ( touch->getLocation().x - anchor_bx  );//计算斜率
			 
			   x = touch->getLocation().x;
			   y = touch->getLocation().y;

			  float r_pingfang = ( jianpan_back->getContentSize().width / 2 
				  - jianpan->getContentSize().width / 2 ) *  (   jianpan_back->getContentSize().width / 2 - jianpan->getContentSize().width / 2 ); 


			  if( x < anchor_bx  ){

				  float t = r_pingfang / ( 1 + k * k );

				  t = sqrt(t);

				  x =  anchor_bx - t;
				  if( y < anchor_by ){
				      y = anchor_by - t * k;
				  }else{
					  y = - t * k + anchor_by ;
				  }

			  }else{
				  float t = r_pingfang / ( 1 + k * k );

				  t = sqrt(t);

				  x =  anchor_bx + t;
				  if( y < anchor_by ){
				     y =  anchor_by + t * k;
				  }else{
					 y =   t * k + anchor_by;
				  }
			  }
			 

	

		}
			 this->set_inner_Yaogan_Place(ccp( x , y ));

		}else{
			this->setVisible(false);
		}

	}

}

三个 与触摸有关的函数


end 函数,把这层设置为不可见。

begin函数,判断是否在 指定区域内的触摸,如果在就 设置该层出现,并 设置图片的位置。

move函数,判断 是否还在需要的触摸 范围内 如果在 就 计算 x,y的位移。最大时 x平方+y平方 = r 平方。


bool Yaogan::check_Can_Be_Show(CCPoint point){

	CCSize size = CCDirector::sharedDirector()->getWinSize();

	float x = point.x;
	float y = point.y;

	

	if(    
		x <= size.width / 3 && x > jianpan_back->getContentSize().width / 2
		
		&& 
		
		y < size.height / 1.75 && y > size.height / 4 
		 
		){
			
		return true;
	}
	return false;
}

int Yaogan::is_Still_Pressed(CCPoint point){

	float x = point.x;
	float y = point.y;
	if( (x - anchor_bx) * (x - anchor_bx) + (y - anchor_by) * (y - anchor_by) <
		( jianpan_back->getContentSize().width / 2   - jianpan->getContentSize().width / 2 ) * 
		( jianpan_back->getContentSize().width / 2   - jianpan->getContentSize().width / 2 ) 
		){
			return 1;
	}
	else if( 
		(x - anchor_bx) * (x - anchor_bx) + ( y - anchor_by ) * ( y - anchor_by )
		   <
		 jianpan_back->getContentSize().width * jianpan_back->getContentSize().width * 4
		
		 &&
		 
		 (x - anchor_bx) * (x - anchor_bx) + (y - anchor_by) * (y - anchor_by) >= 
		 ( jianpan_back->getContentSize().width / 2   - jianpan->getContentSize().width / 2 ) * 
		 ( jianpan_back->getContentSize().width / 2   - jianpan->getContentSize().width / 2 )  

		 ){
		return 2;
	}
	
	return 0;

}

两个判断重合的函数。




本期的教你打灰机就到此结束了,欢迎大家多交流>.<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值