【cocos2d-x-3.2】【高仿微信打飞机系列一】【开始界面 子d生成 背景滑动 主飞机】

【cocos2d-x-3.2】【高仿微信打飞机系列一】【开始界面 子d生成 背景滑动 主飞机】,第1张

概述看了cocos2d有一段时间了,简单的小游戏还是可以写出来。这个过程主要还是看,而很少动手去写,这样本身水平很难提高。就好比看完设计模式,现在依旧不会用,时间一久,也忘记的差不多了。俗话说,纸上得来终觉浅,绝知此事要躬行。因此,决定写一个高仿发飞机的小游戏,虽然简单,但还是要坚持写完。 这个系列主要还是基于我想到哪就写到哪,不定期更新。 1.开始界面 首先,我们得找到微信打飞机的图片资源,直接到下

看了cocos2d有一段时间了,简单的小游戏还是可以写出来。这个过程主要还是看,而很少动手去写,这样本身水平很难提高。就好比看完设计模式,现在依旧不会用,时间一久,也忘记的差不多了。俗话说,纸上得来终觉浅,绝知此事要躬行。因此,决定写一个高仿发飞机的小游戏,虽然简单,但还是要坚持写完。

这个系列主要还是基于我想到哪就写到哪,不定期更新。

1.开始界面

首先,我们得找到微信打飞机的图片资源,直接到下面链接下载就可以了:

http://download.csdn.net/detail/q100036q/7524993

解压后:


资源图片准备就绪,我们就可以开始编码工作了,依旧是看图写代码,一步一步搭建。

开始画面很简单,一张背景图片再加一个animation,便构成了开始界面。

代码如下:

#ifndef _START_GAME_SCENE_H_#define _START_GAME_SCENE_H_#include "cocos2d.h"USING_NS_CC;class StartGameScene : public Layer{public:    static cocos2d::Scene* createScene();	virtual bool init();	CREATE_FUNC(StartGameScene);	voID loadingHandler();	voID loadingDone();};#endif#include "StartGameScene.h"#include "PlayGameScene.h"Scene* StartGameScene::createScene(){    // 'scene' is an autorelease object    auto scene = Scene::create();        // 'layer' is an autorelease object    auto layer = StartGameScene::create();    // add layer as a child to scene    scene->addChild(layer);    // return the scene    return scene;}// on "init" you need to initialize your instancebool StartGameScene::init(){    //////////////////////////////    // 1. super init first    if ( !Layer::init() )    {        return false;    }    Size visibleSize = Director::getInstance()->getVisibleSize();    Vec2 origin = Director::getInstance()->getVisibleOrigin();    // add background image    auto sprite = Sprite::create("shoot_background/background.png");    // position the sprite on the center of the screen    sprite->setposition(Vec2(visibleSize.wIDth/2 + origin.x,visibleSize.height/2 + origin.y));    // add the sprite as a child to this layer    this->addChild(sprite,0);    //加载页面	loadingHandler();    return true;}//loading handlervoID StartGameScene::loadingHandler(){	Size visibleSize = Director::getInstance()->getVisibleSize();	//start:开始界面的animation	auto loadingSp = Sprite::create();	loadingSp->setposition(Point(visibleSize.wIDth / 2,visibleSize.height / 2));	this->addChild(loadingSp,1);		Vector<SpriteFrame*> frameList;	for(int i = 1; i <=4; i++)	{		SpriteFrame* sf = SpriteFrame::create(String::createWithFormat("shoot_background/game_loading%d.png",i)->_string,Rect(0,186,38));		frameList.pushBack(sf);	}		Animation* an = Animation::createWithSpriteFrames(frameList,0.5f);	auto animate = Animate::create(an);	auto repeat = Repeat::create(animate,3);//播放三次	//回调函数	auto callback = CallFunc::create(CC_CALLBACK_0(StartGameScene::loadingDone,this));	auto sequence = Sequence::create(repeat,callback,NulL);	loadingSp->runAction(sequence);	//end:开始界面的animation}//开始界面播放完,直接进入游戏场景voID StartGameScene::loadingDone(){	Director::getInstance()->replaceScene(PlayGameScene::createScene());}

显示效果如下:


2.背景移动

进入游戏后,要让背景图片动起来,并且无缝衔接。实际上,用两张背景图片就可以达到这种效果。当第一张移出屏幕的时候,立即放置到最上面,衔接第二张,达到无缝衔接的效果。主要代码如下:

	//run the background 	auto bg_1 = Sprite::create("shoot_background/background.png");	bg_1->setAnchorPoint(Point(0,0 ));	bg_1->setposition(Point(0,0));	bg_1->setTag(BG_1);	this->addChild(bg_1,0);	auto bg_2 = Sprite::create("shoot_background/background.png");	bg_2->setAnchorPoint(Point(0,0 ));	bg_2->setposition(Point(0,bg_1->getContentSize().height));	bg_2->setTag(BG_2);	this->addChild(bg_2,0);	//run background image	this->schedule(schedule_selector(PlayGameScene::runBackground),0.01f);voID PlayGameScene::runBackground(float dt){	auto visibleSize = Director::getInstance()->getVisibleSize();	auto bg_1 = this->getChildByTag(BG_1);	auto bg_2 = this->getChildByTag(BG_2);	int bg_height = bg_1->getContentSize().height;	bg_1->setpositionY(bg_1->getpositionY() - bg_speed);	bg_2->setpositionY(bg_2->getpositionY() - bg_speed);	//bg2移出屏幕后衔接在bg1后面	if(bg_2->getpositionY() <= 0)	{		bg_1->setpositionY(bg_2->getpositionY() + bg_height);	}	//bg1移出屏幕后衔接在bg2后面	if(bg_1->getpositionY() <= 0)	{		bg_2->setpositionY(bg_1->getpositionY() + bg_height);	}}
3.加载主飞机

经过步骤2,背景也可以无缝移动了,把主飞机(hero_plane)放上去,并且注册他的触碰事件检测,也就是我们手指触碰主飞机的时候,飞机能够跟着我们手指移动而移动。这样的效果也很简单,在层中去注册touchevent事件处理。点击时如果是touch飞机,设置一个标志位,touchmove事件的时候,不断去更新飞机的位置,这样就可以达到效果了。
主要代码如下:

	//add plane hero 	Sprite* hero = Sprite::create("hero1.png");	PlaneHero* hero_plane = PlaneHero::create(hero);	hero_plane->setposition(Point(visibleSize.wIDth / 2,visibleSize.height / 2));	hero_plane->setTag(HERO_PLANE);	hero_plane->setAnchorPoint(Point(0,0));	this->addChild(hero_plane,1);	//touch event handler	auto touchListener = EventListenertouchOneByOne::create();	touchListener->setSwallowtouches(true);	touchListener->ontouchBegan = CC_CALLBACK_2(PlayGameScene::ontouchBegan,this);	touchListener->ontouchmoved = CC_CALLBACK_2(PlayGameScene::ontouchmoved,this);	touchListener->ontouchCancelled = CC_CALLBACK_2(PlayGameScene::ontouchended,this);	_eventdispatcher->addEventListenerWithSceneGraPHPriority(touchListener,this);//touch event handlerbool PlayGameScene::ontouchBegan(touch *touch,Event* event){	Point touchPoint = touch->getLocation();	btouchPlane = false;	auto hero_plane = this->getChildByTag(HERO_PLANE);	Point hero_pos = hero_plane->getposition();	Size hero_size = hero_plane->getContentSize();	log("hero_pos x = %f,y = %f",hero_pos.x,hero_pos.y);	log("touchPoint x = %f,touchPoint.x,touchPoint.y);	log("hero_size wIDth = %f,height = %f",hero_size.wIDth,hero_size.height);	if(touchPoint.x >= hero_pos.x && touchPoint.x <= (hero_pos.x + hero_size.wIDth) && touchPoint.y >= hero_pos.y && touchPoint.y <= (touchPoint.y + hero_size.height))	{		//touch the plane,mark this flag for use		btouchPlane = true;	}	return true;}voID PlayGameScene::ontouchmoved(touch *touch,Event* event){	if(btouchPlane == true)	{		//move the hero_pane with out touch on screen		auto hero_plane = this->getChildByTag(HERO_PLANE);		Point pos = touch->getLocation();		hero_plane->setposition(pos);	}}voID PlayGameScene::ontouchended(touch *touch,Event* event){	btouchPlane = false;}
4.子d管理器

首先,我们写一个基类,用来绑定一个精灵,所有的飞机,子d都会继承他。

#ifndef _ENTITY_H_#define _ENTITY_H_#include "cocos2d.h"USING_NS_CC;class Entity : public Node{public:	Entity();	~Entity();	voID bindSprite(Sprite* sprite);	Sprite* getSprite();private:	Sprite* m_sprite;};#endif#include "Entity.h"Entity::Entity(){	m_sprite = NulL;}Entity::~Entity(){}voID Entity::bindSprite(Sprite* sprite){	if(this->m_sprite != NulL)	{		m_sprite->removeFromParentAndCleanup(true);	}	this->m_sprite = sprite;	this->addChild(m_sprite);	Size size = m_sprite->getContentSize();	this->setContentSize(size);}Sprite* Entity::getSprite(){	return this->m_sprite;}
接着,写一个子d的基类,继承自Entity,他包含子d的共有属性。不同的子d类型都会继承自这个子d基类。方便扩展。
#ifndef _BulLETBASE_BASE_H_#define _BulLETBASE_BASE_H_#include "Entity.h"#define SPEED_DEFAulT 10#define SPEED_norMAL 5class BulletBase : public Entity{public:	BulletBase();	~BulletBase();	//子d是否在使用中	voID setUsed(bool isUsed);	bool isUsed();		bool isArrive();	//设置子d速度	voID setSpeed(int speed);	int getSpeed();	//是否飞出屏幕	bool isMoveOutScreen();	voID setIsMoveOutScreen(bool outScreen);	//是否加进层里面	//bool isAddInLayer();	//voID setIsAddInLayer(bool inLayer);protected:	bool m_isArrive;	int  m_speed;private:	bool m_isUsed;	bool m_isOutScreen;	//bool m_isAddInLayer;};#endif#include "BulletBase.h"BulletBase::BulletBase(){	m_isUsed = false;	m_isArrive = false;	m_speed = SPEED_norMAL;	m_isOutScreen = false;	//m_isAddInLayer = false;}BulletBase::~BulletBase(){}voID BulletBase::setUsed(bool isUsed){	this->m_isUsed = isUsed;}bool BulletBase::isUsed(){	return this->m_isUsed;}	bool BulletBase::isArrive(){	return this->m_isArrive;}//设置子d速度voID BulletBase::setSpeed(int speed){	this->m_speed = speed;}int BulletBase::getSpeed(){	return this->m_speed;}//是否已经飞出屏幕bool BulletBase::isMoveOutScreen(){	return this->m_isOutScreen;}voID BulletBase::setIsMoveOutScreen(bool outScreen){	this->m_isOutScreen = outScreen;}#if 0//是否加进层里面bool BulletBase::isAddInLayer(){	return this->m_isAddInLayer;}voID BulletBase::setIsAddInLayer(bool inLayer){	this->m_isAddInLayer = inLayer;}#endif
紧接着,写一个普通类型的子d,在这里其实主要是写入子d的速度。不同类型的子d拥有不同的属性值,我们先简单的设置子d的速度就可以。以后需要扩展直接对这个类进行。
#ifndef _BulLET_norMAL_H_#define _BulLET_norMAL_H_#include "BulletBase.h"class Bulletnormal : public BulletBase{public:	Bulletnormal();	~Bulletnormal();	CREATE_FUNC(Bulletnormal);	virtual bool init();	static Bulletnormal* create(Sprite* sprite);	bool init(Sprite* sprite);private:	voID moveEnd();};#endif
#include "Bulletnormal.h"Bulletnormal::Bulletnormal(){	m_speed = SPEED_norMAL;}Bulletnormal::~Bulletnormal(){}bool Bulletnormal::init(){	return true;}Bulletnormal* Bulletnormal::create(Sprite* sprite){	Bulletnormal* bnor = new Bulletnormal();	if(bnor && bnor->init(sprite))	{		bnor->autorelease();	}	else	{		CC_SAFE_DELETE(bnor);	}	return bnor;}bool Bulletnormal::init(Sprite* sprite){	bool ret = false;	bindSprite(sprite);	ret = true;	return ret;}voID Bulletnormal::moveEnd(){	m_isArrive = true;}
最后,创建子d管理器,生成子d,保存到一个列表里面,需要的时候直接取出。同时,子d的飞行也在管理器中做处理,不断检测子d并且设置子d的运行。
#ifndef _BulLET_MANAGER_H_#define _BulLET_MANAGER_H_#include "cocos2d.h"USING_NS_CC;#define BulLET_MAX_CACHE_NUM 20 //子d缓存数量class BulletBase;class BulletManager : public Node{public:	BulletManager();	~BulletManager();	static BulletManager* create();	bool init();	//获取未用的子d	BulletBase* getUnusedBullet();private:	Vector<BulletBase*> m_bulletList;//子d列表,保存子d	voID createBullets();//创建缓存子d	voID bulletLogicCheck(float dt);//子d逻辑};#endif#include "BulletManager.h"#include "BulletBase.h"#include "Bulletnormal.h"BulletManager::BulletManager(){}BulletManager::~BulletManager(){}BulletManager* BulletManager::create(){	BulletManager* bulletMgr = new BulletManager();	if(bulletMgr && bulletMgr->init())	{		bulletMgr->autorelease();	}	else	{		CC_SAFE_DELETE(bulletMgr);	}	return bulletMgr;}bool BulletManager::init(){	//创建子d列表	createBullets();	log("m_bulletList size() = %d",m_bulletList.size());	//循环检测子d列表	this->schedule(schedule_selector(BulletManager::bulletLogicCheck));	return true;}//获取未用的子dBulletBase* BulletManager::getUnusedBullet(){	log("m_bulletList size() = %d",m_bulletList.size());	for(int i = 0; i < m_bulletList.size(); i++)	{		BulletBase* bullet = m_bulletList.at(i);		if(bullet->isUsed() == false)		{			bullet->setUsed(true);			bullet->setIsMoveOutScreen(false);			return bullet;		}	}#if 0 //i don't kNow why 	for(auto bullet : m_bulletList)	{		if(bullet->isUsed() == false)		{			bullet->setUsed(true);			bullet->setIsMoveOutScreen(false);			return bullet;		}	}#endif	log("no bullet unused");	return NulL;}//创建子d缓存voID BulletManager::createBullets(){	BulletBase* bullet = NulL;	for(int i = 0; i < BulLET_MAX_CACHE_NUM; i++)	{		auto bullet_sprite = Sprite::create("bullet1.png");		bullet = Bulletnormal::create(bullet_sprite);		bullet->setUsed(false);		bullet->setIsMoveOutScreen(false);		m_bulletList.pushBack(bullet);		this->addChild(bullet);	}	log("m_bulletList size() = %d",m_bulletList.size());}//检测子dvoID BulletManager::bulletLogicCheck(float dt){	auto visibleSize = Director::getInstance()->getVisibleSize();	for(auto bullet : m_bulletList)	{		if(bullet->isUsed() == true)		{			//子d运行			int posY = bullet->getpositionY();			posY += SPEED_DEFAulT;			bullet->setpositionY(posY);			//out of screen			if(posY >= visibleSize.height)			{				bullet->setIsMoveOutScreen(true);				bullet->setUsed(false);			}		}	}}

以上全部写完,基本的画面就出来了,画面如下



好了 第一篇就先写到这里,后续会写第二篇。

总结

以上是内存溢出为你收集整理的【cocos2d-x-3.2】【高仿微信打飞机系列一】【开始界面 子d生成 背景滑动 主飞机】全部内容,希望文章能够帮你解决【cocos2d-x-3.2】【高仿微信打飞机系列一】【开始界面 子d生成 背景滑动 主飞机】所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1045254.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存