Cocos2d-x 《雷电大战》-精灵随手指移动,你点哪我走哪!

林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

本文要实现飞机游戏中,人的手指按着飞机,就能拖着飞机走动,这里实现了当你手指按在手机的图片上,手指一直按着屏幕,飞机就会跟着你走。同时,还加入了边界判断条件,让飞机在你的视野内移动,实现的效果完全和我们手机上的飞机游戏一样。

效果:

Cocos2d-x版本:3.4

工程环境:VS30213

一、代码编写

1、头文件GameMain.h

/**
*@作者 林炳文(邮箱:[email protected])
*@博客 http://blog.csdn.net/evankaka
*@时间 2015.3.8
*@功能 游戏的主界面
*/
#ifndef __GameMain_H__
#define __GameMain_H__
#include "BackLayerDown.h"
#include "BackLayerUp.h"
#include "cocos2d.h"
USING_NS_CC;
class GameMain : public cocos2d::Layer
{
public:
    static cocos2d::Scene* createScene();
    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 onTouchEened(cocos2d::Touch *touch, cocos2d::Event *unused_event);
	virtual void onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_even);

    CREATE_FUNC(GameMain);
private:
	bool isHeroPlaneControl;//飞机是否被控制着
	float mDeltaX;//英雄飞机随手指移动时的X偏移量
	float mDeltaY;//英雄飞机随手指移动时的Y偏移量
	Sprite *mHeroPlane;//英雄飞机
};

#endif // __GameMain_H__

然后在GameMain.cpp中增加:

#include "GameMain.h"
USING_NS_CC;
Scene* GameMain::createScene()
{
    auto scene = Scene::create();
    auto layer = GameMain::create();
    scene->addChild(layer);
    return scene;
}

bool GameMain::init()
{
	Size visibleSize = Director::getInstance()->getVisibleSize();
	Point origin = Director::getInstance()->getVisibleOrigin();
	//这是地面图层
	this->addChild(BackLayerUp::create());
	//这是白云图层
	this->addChild(BackLayerDown::create());

	//加个飞机
	mHeroPlane = Sprite::create("air1.png");
	mHeroPlane->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 5));
	this->addChild(mHeroPlane, 1, 100);
	isHeroPlaneControl = false;

	//打开触摸,增加触摸监听事件
	this->setTouchEnabled(true);
	auto listen = EventListenerTouchOneByOne::create();
	listen->onTouchBegan = CC_CALLBACK_2( GameMain::onTouchBegan,this);
	listen->onTouchMoved = CC_CALLBACK_2(GameMain::onTouchMoved, this);
	listen->onTouchEnded = CC_CALLBACK_2(GameMain::onTouchEened, this);
	listen->onTouchCancelled = CC_CALLBACK_2(GameMain::onTouchCancelled, this);
	listen->setSwallowTouches(false);//不截取触摸事件
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen,this);

    return true;
}
bool  GameMain::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event){

	Point mHeroPos = mHeroPlane->getPosition();
	Point mBeganPos = touch->getLocationInView();
	mBeganPos = Director::getInstance()->convertToGL(mBeganPos);

	//判断当前手指按下区域是否是英雄飞机的区域,并且计算飞机要移动时的偏移量
	if (mBeganPos.x > mHeroPos.x - mHeroPlane->getContentSize().width / 2 && mBeganPos.x<mHeroPos.x + mHeroPlane->getContentSize().width / 2 &&
		mBeganPos.y>mHeroPos.y - mHeroPlane->getContentSize().height / 2 && mBeganPos.y < mHeroPos.y + mHeroPlane->getContentSize().height / 2){
		isHeroPlaneControl = true;
		//計算偏移量
		mDeltaX = mBeganPos.x - mHeroPos.x;
		mDeltaY = mBeganPos.y - mHeroPos.y;

	}

	return true;
}
void  GameMain::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event){
	if (isHeroPlaneControl){
		Point mMovedPos = touch->getLocationInView();
		mMovedPos = Director::getInstance()->convertToGL(mMovedPos);

		Size visibleSize = Director::getInstance()->getVisibleSize();
		Point origin = Director::getInstance()->getVisibleOrigin();
		float x = mMovedPos.x - mDeltaX;//記得減去偏移量
		float y = mMovedPos.y - mDeltaY;

		if (x <= mHeroPlane->getContentSize().width / 2 + origin.x)//x到达屏幕左边界
			x = mHeroPlane->getContentSize().width / 2 + origin.x;
		else if (x >= visibleSize.width - mHeroPlane->getContentSize().width / 2)//x到达屏幕右边界
			x = visibleSize.width - mHeroPlane->getContentSize().width / 2;

		if (y <= mHeroPlane->getContentSize().height / 2 + origin.y)//y到达屏幕下边界
			y = mHeroPlane->getContentSize().height / 2 + origin.y;
		else if (y >= visibleSize.height - mHeroPlane->getContentSize().height / 2)//x到达屏幕上边界
			y = visibleSize.height - mHeroPlane->getContentSize().height/ 2;

		//飞机跟随手指移动
		mHeroPlane->setPosition(Vec2(x,y));
	}
}
void  GameMain::onTouchEened(cocos2d::Touch *touch, cocos2d::Event *unused_event){
	isHeroPlaneControl = false;
}
void  GameMain::onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_even){
	isHeroPlaneControl = false;
}

这里再说一写主要函数:

头文件增加触摸事件:

	virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);
	virtual void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event);
	virtual void onTouchEened(cocos2d::Touch *touch, cocos2d::Event *unused_event);
	virtual void onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_even);

实现文件开启触摸事件监听:

//打开触摸,增加触摸监听事件
	this->setTouchEnabled(true);
	auto listen = EventListenerTouchOneByOne::create();
	listen->onTouchBegan = CC_CALLBACK_2( GameMain::onTouchBegan,this);
	listen->onTouchMoved = CC_CALLBACK_2(GameMain::onTouchMoved, this);
	listen->onTouchEnded = CC_CALLBACK_2(GameMain::onTouchEened, this);
	listen->onTouchCancelled = CC_CALLBACK_2(GameMain::onTouchCancelled, this);
	listen->setSwallowTouches(false);//不截取触摸事件
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen,this);

然后就是触摸事件 的处理了:

bool  GameMain::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event){

	Point mHeroPos = mHeroPlane->getPosition();
	Point mBeganPos = touch->getLocationInView();
	mBeganPos = Director::getInstance()->convertToGL(mBeganPos);

	//判断当前手指按下区域是否是英雄飞机的区域,并且计算飞机要移动时的偏移量
	if (mBeganPos.x > mHeroPos.x - mHeroPlane->getContentSize().width / 2 && mBeganPos.x<mHeroPos.x + mHeroPlane->getContentSize().width / 2 &&
		mBeganPos.y>mHeroPos.y - mHeroPlane->getContentSize().height / 2 && mBeganPos.y < mHeroPos.y + mHeroPlane->getContentSize().height / 2){
		isHeroPlaneControl = true;
		//計算偏移量
		mDeltaX = mBeganPos.x - mHeroPos.x;
		mDeltaY = mBeganPos.y - mHeroPos.y;

	}

	return true;
}
void  GameMain::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event){
	if (isHeroPlaneControl){
		Point mMovedPos = touch->getLocationInView();
		mMovedPos = Director::getInstance()->convertToGL(mMovedPos);

		Size visibleSize = Director::getInstance()->getVisibleSize();
		Point origin = Director::getInstance()->getVisibleOrigin();
		float x = mMovedPos.x - mDeltaX;//記得減去偏移量
		float y = mMovedPos.y - mDeltaY;

		if (x <= mHeroPlane->getContentSize().width / 2 + origin.x)//x到达屏幕左边界
			x = mHeroPlane->getContentSize().width / 2 + origin.x;
		else if (x >= visibleSize.width - mHeroPlane->getContentSize().width / 2)//x到达屏幕右边界
			x = visibleSize.width - mHeroPlane->getContentSize().width / 2;

		if (y <= mHeroPlane->getContentSize().height / 2 + origin.y)//y到达屏幕下边界
			y = mHeroPlane->getContentSize().height / 2 + origin.y;
		else if (y >= visibleSize.height - mHeroPlane->getContentSize().height / 2)//x到达屏幕上边界
			y = visibleSize.height - mHeroPlane->getContentSize().height/ 2;

		//飞机跟随手指移动
		mHeroPlane->setPosition(Vec2(x,y));
	}
}
void  GameMain::onTouchEened(cocos2d::Touch *touch, cocos2d::Event *unused_event){
	isHeroPlaneControl = false;
}
void  GameMain::onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_even){
	isHeroPlaneControl = false;
}

方法很简单,代码量也很少,有需要的把上面的自己拿过去,把图片改改,把类名改改就可以了。

其实这里应该把英雄和移动事件单独写一个类,然后在GameMain里头来调用,因为英雄这个类我还构思好,所以先这样写,后头会把英雄飞机单独提取出来成为一个类,就不会在GameMain里头写这么多了;

效果:

\

效果很好,飞机能跟随移动并且不会跑出屏幕范围

二、思路说明

1、首先在onTouchBegan判断触摸点是否在英雄飞机的图片矩形内,若在这个范围内,刚将布尔型的mHeroPlaneControl设置为true,并且计算触摸点的横纵坐标与英雄飞机的锚点坐标的差值。

2、因为要让英雄飞机移动,要修改锚点位置,必须知道锚点位置与触摸位置的偏移量,之后才可以通过这个偏移量设置主角的位置。

3、判断英雄飞机是否跑出屏幕范围了,如果是,就将它设置在边界处,详看上面的两个if判断。

4、在onTouchMoved中,若mHeroPlaneControl为true,说明可以移动英雄飞机。

林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

若你觉得此文对你有用,那就帮我顶一下~~谢谢啦!

时间: 2024-10-14 06:25:04

Cocos2d-x 《雷电大战》-精灵随手指移动,你点哪我走哪!的相关文章

Cocos2d-x《雷电大战》(3)-子弹无限发射

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 本文要实现雷电游戏中,游戏一開始,英雄飞机就无限发射子弹的功能. 这里的思想是单独给子弹弄一个层.在这个层不设置一个定时器,每隔一个时间,依据当前英雄飞机传入的位置,生成子弹,并设置子弹的移动事件,和移动后的事件(就是把子弹删除掉,节省内存). 终于效果: Cocos2d-x版本号:3.4 project环境:VS30213 一.英雄子弹层 1.HeroBulletLayer.h /** *

Cocos2d-x《雷电大战》(4)-策略模式实现不同子弹切换!!

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 本文从设计模式中的策略模式入手,主讲了飞机大战中英雄飞机切换不同的子弹.这里分为三种子弹.第一种:每次发一个子弹,垂直发射;第二种:每次发两个子弹,两个都是垂直发射:第三种;每次发三个子弹,两边的子弹有一定的角度,而中间的子弹垂直发射;设计模式是游戏开发经常用到的思想,建议有兴趣的同学可以好好研究下!好了,下面开始吧. 效果如下: Cocos2d-x版本:3.4 工程环境:VS30213 一

Cocos2d-x《雷电大战》(5)-单例模式英雄飞机闪亮登场!

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 本文将实现用单例模式实现一个英雄飞机类的设计,单例模式是游戏开发中最常用到的一种设计模式,原理也比较简单,仔细研究下就可以掌握好. 来看看效果: Cocos2d-x版本:3.4 工程环境:VS30213 一.单例模式解析 单例模式也称为单件模式.单子模式,可能是使用最广泛的设计模式.其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享.有很多地方需要这样的功

Cocos2d-x游戏《雷电大战》开源啦!要源码要资源快快来~~

写在前面的话:这是笔者开发的第二个小游戏<雷电大战>,之前就过这个游戏和<赵云要格斗>一样,最终将会开源.由于自己的一些个人原因.这个游戏还没有完成,但是许多网友都过来寻求代码或资源,本着开源的精神,笔者今天将它们共享给出大家. 注:目前游戏还没有完成,代码全是笔者原创,资源有一部分原创,有一部分网上搜集. 若是觉得本项目对你有用,那么请给辛苦的笔者的GitHub右上角Star一颗星星!不胜感激---- 下载地址 https://github.com/appleappleapple

Cocos2d-x 让精灵随手指移动起来二(简单实现)

void HelloWorld::ccTouchMoved(cocos2d::CCTouch *touch, cocos2d::CCEvent *event) { CCSize winSize = CCDirector::sharedDirector()->getVisibleSize(); if (m_ship) { CCPoint pos = touch->getDelta();//获取触点当前位置与较早前的位置的差距 CCPoint currentPos = m_ship->get

精灵随手指移动起来

效果图: 程序代码: bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); CCPoint origin = CCDirector::sharedDirector()->

Cocos2d-x 《雷电大战》-双层地图无限滚动

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 本文要实现飞机射击游戏中的地图无限滚动的功能,这里分为两个层,一个层无限向下滚动,一个层无限向上滚动,这样子结合起来效果就非常有层次感,也非常逼真,这里我把地图层都写成一个类,自己把地图改下,就可以成为你自己的了!下面,我们开始吧 先来看看效果: Cocos2d-x版本:3.4 工程环境:VS30213 一.实现思路 其实就是两张图片,然后同时一起向下(向上)滚动,当一张图片完全出视野后,就

Cocos2d-x《雷电大战》(6) 智能敌机AI来袭--飞行路径算法设计与实现(上)

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 本文要实现飞机类游戏中的一连串飞机的跟随出和和并行出出.而网上找了一些Cocos2dx开发的飞行类游戏,都只找到一些简单的智能敌机.基本上没什么AI,这样游戏玩起来就太没意思了.然后又去找敌机飞行路径的相关资料,发现相关的也很少.想想还是自己来设计吧! 飞机类游戏设计中,智机的飞行路径设计和智能子弹的设计绝对一个飞行类游戏好坏是的核心.敌机智能也是分级别的.BOSS机就不说了,而飞行游戏由于

Cocos2d-x《雷电大战》-双层地图无限滚动

本文要实现飞机射击游戏中的地图无限滚动的功能,这里分为两个层,一个层无限向下滚动,一个层无限向上滚动,这样子结合起来效果就非常有层次感,也非常逼真,这里我把地图层都写成一个类,自己把地图改下,就可以成为你自己的了!下面,我们开始吧 先来看看效果: Cocos2d-x版本:3.4 工程环境:VS30213 一.实现思路 其实就是两张图片,然后同时一起向下(向上)滚动,当一张图片完全出视野后,就把它调到最上面.形成两个图片交替出现,不过,一般为游戏中我们都感觉像是一张图片,那是因为两张图片的头尾连接