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

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

     本文要实现飞机射击游戏中的地图无限滚动的功能,这里分为两个层,一个层无限向下滚动,一个层无限向上滚动,这样子结合起来效果就非常有层次感,也非常逼真,这里我把地图层都写成一个类,自己把地图改下,就可以成为你自己的了!下面,我们开始吧

先来看看效果



Cocos2d-x版本:3.4

工程环境:VS30213

 

一、实现思路

       其实就是两张图片,然后同时一起向下(向上)滚动,当一张图片完全出视野后,就把它调到最上面。形成两个图片交替出现,不过,一般为游戏中我们都感觉像是一张图片,那是因为两张图片的头尾连接处是连起来的。原理我画了些图:

二、代码

1、无限向下滚动BackLayerDown类

头文件:

#ifndef __BackLayerDown_H__
#define __BackLayerDown_H__
/**
*功能 實現無限地圖向下滾動
*作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka)
*時間 2015.2.27
*/
#include "cocos2d.h"
#define MAP_1_Tag   1       // 宏定义两个Map的Tag  
#define MAP_2_Tag   2 
class BackLayerDown : public cocos2d::Layer
{
public:
    virtual bool init();
    CREATE_FUNC(BackLayerDown);
private:
	void update(float time);
	virtual void onExit();
};

#endif // __BackLayerDown_H__

实现文件:

#include "BackLayerDown.h"

USING_NS_CC;


bool BackLayerDown::init()
{
  
    if ( !Layer::init() )
    {
        return false;
    }
    
	Size visibleSize = Director::getInstance()->getVisibleSize();
	Point origin = Director::getInstance()->getVisibleOrigin();

	Sprite* map1 = Sprite::create("back3_1.png");
	Sprite* map2 = Sprite::create("back3_2.png");
	map1->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
	map2->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height + origin.y + map2->getContentSize().height / 2));
	this->addChild(map1, 0, MAP_1_Tag);
	this->addChild(map2, 0, MAP_2_Tag);
	this->scheduleUpdate();

    
    return true;
}

//移動并判斷背景
void BackLayerDown::update(float time)
{
	Size visibleSize = Director::getInstance()->getVisibleSize();
	Point origin = Director::getInstance()->getVisibleOrigin();

	Sprite* temMap1 = (Sprite*)this->getChildByTag(MAP_1_Tag);
	Sprite* temMap2 = (Sprite*)this->getChildByTag(MAP_2_Tag);

	temMap1->setPositionY(temMap1->getPositionY() - 1);
	temMap2->setPositionY(temMap2->getPositionY() - 1);

	if (temMap1->getPositionY() + temMap1->getContentSize().height / 2 <= origin.y)
	{
		float offset = temMap1->getPositionY() + temMap1->getContentSize().height / 2 - origin.y;
		temMap1->setPosition(Vec2(visibleSize.width / 2 + origin.x, temMap1->getContentSize().height / 2 + origin.y + visibleSize.height + offset));
	}

	if (temMap2->getPositionY() + temMap2->getContentSize().height / 2 <= origin.x)
	{
		float offset = temMap2->getPositionY() + temMap2->getContentSize().height / 2 - origin.y;
		temMap2->setPosition(Vec2(visibleSize.width / 2 + origin.x, temMap2->getContentSize().height / 2 + origin.y + visibleSize.height + offset));
	}
}

void BackLayerDown::onExit()
{
	this->unscheduleUpdate();
	Layer::onExit();
}


2、无限向上滚动BackLayerUp类

头文件:

#ifndef __BackLayerUp_H__
#define __BackLayerUp_H__
/**
*功能 實現無限地圖向上滾動
*作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka)
*時間 2015.2.27
*/
#include "cocos2d.h"
#define MAP_1_Tag   1       // 宏定义两个Map的Tag  
#define MAP_2_Tag   2 
class BackLayerUp : public cocos2d::Layer
{
public:
    virtual bool init();
    CREATE_FUNC(BackLayerUp);
private:
	void update(float time);
	virtual void onExit();
};

#endif // __BackLayerUp_H__

实现文件:

#include "BackLayerUp.h"

USING_NS_CC;


bool BackLayerUp::init()
{
  
    if ( !Layer::init() )
    {
        return false;
    }
    
	Size visibleSize = Director::getInstance()->getVisibleSize();
	Point origin = Director::getInstance()->getVisibleOrigin();

	Sprite* map1 = Sprite::create("back4_2.png");
	Sprite* map2 = Sprite::create("back4_1.png");
	map1->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
	map2->setPosition(Vec2(visibleSize.width / 2 + origin.x, origin.y - map2->getContentSize().height / 2));
	this->addChild(map1, 0, MAP_1_Tag);
	this->addChild(map2, 0, MAP_2_Tag);
	this->scheduleUpdate();

    
    return true;
}

//移動并判斷背景
void BackLayerUp::update(float time)
{
	Size visibleSize = Director::getInstance()->getVisibleSize();
	Point origin = Director::getInstance()->getVisibleOrigin();

	Sprite* temMap1 = (Sprite*)this->getChildByTag(MAP_1_Tag);
	Sprite* temMap2 = (Sprite*)this->getChildByTag(MAP_2_Tag);

	temMap1->setPositionY(temMap1->getPositionY() + 1);
	temMap2->setPositionY(temMap2->getPositionY() + 1);

	if (temMap1->getPositionY() - temMap1->getContentSize().height / 2 >= visibleSize.height)
	{
	float offset = temMap1->getPositionY() - temMap1->getContentSize().height / 2 - visibleSize.height;
	temMap1->setPosition(Vec2(visibleSize.width / 2 + origin.x, -temMap1->getContentSize().height / 2 - origin.y - offset));
	}

	if (temMap2->getPositionY() - temMap2->getContentSize().height / 2 >= visibleSize.height)
	{
	float offset = temMap2->getPositionY() - temMap2->getContentSize().height / 2 - visibleSize.height;
	temMap2->setPosition(Vec2(visibleSize.width / 2 + origin.x, -temMap2->getContentSize().height / 2 - origin.y  - offset));
	}
}

void BackLayerUp::onExit()
{
	this->unscheduleUpdate();
	Layer::onExit();
}

3、说明

   其实这两个类可以写在一起的,但是这里我为了能让不同的需要分开,把它们分别写开了,要注意上面判断的方法,无限向下和无限向上判断方法是不样的,而且,这里为了防止出现黑边,要记得设置位置时要加上一定的偏移量,如上面函数中的offset,这里非常重要,如果没边上这个东东,有可能两张图片在切换时,有出现黑边。

 

三、使用方法

    在要用到的地方,把头文件加上

   1: #include "BackLayerDown.h"
   2: #include "BackLayerUp.h"

然后在工程的init()函数添加:

   1: Size visibleSize = Director::getInstance()->getVisibleSize();
   2: Point origin = Director::getInstance()->getVisibleOrigin();
   3: //这是地面图层
   4: this->addChild(BackLayerUp::create());
   5: //这是白云图层
   6: this->addChild(BackLayerDown::create());
   7:  
   8: //加个飞机
   9: Sprite *airplane_sprite = Sprite::create("air1.png");
  10: airplane_sprite->setPosition(Vec2(visibleSize.width / 2, visibleSize.height/ 5));
  11: this->addChild(airplane_sprite);

效果:


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



  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
cocos2dx 雷电MoonWarriors_游戏源码 #include "GameLayer.h" #include "SimpleAudioEngine.h" #include "Bullet.h" #include "Resource.h" #include "Config.h" #include "Enemy.h" #include "Effect.h" #include "GameOver.h" #include "PauseLayer.h" using namespace cocos2d; using namespace CocosDenshion; bool isPaused = false; GameLayer::GameLayer():m_state(statePlaying),m_time(0),m_ship(NULL),m_backSky(NULL),m_backSkyHeight(0),m_backSkyRe(NULL),m_backTileMap(NULL),m_backTileMapHeight(0),m_backTileMapRe(NULL),m_isBackSkyReload(false),m_isBackTileReload(false),m_lbScore(NULL),m_lifeCount(NULL), m_tempScore(0) { } GameLayer::~GameLayer() { if (m_levelManager) { delete m_levelManager; } play_bullet->release(); enemy_bullet->release(); enemy_items->release(); } bool GameLayer::init() { if (!CCLayer::init()) { return false; } // 开启触摸 this->setTouchEnabled(true); // 创建数组,需要retain一下 play_bullet = CCArray::create(); play_bullet->retain(); enemy_bullet = CCArray::create(); enemy_bullet->retain(); enemy_items = CCArray::create(); enemy_items->retain(); m_state = statePlaying; Enemy::sharedEnemy(); Effect::sharedExplosion(); Config::sharedConfig()->resetConfig(); winSize = CCDirector::sharedDirector()->getWinSize(); m_levelManager = new LevelManager(this); //初始化背景 initBackground(); m_screenRec = CCRectMake(0, 0, winSize.width, winSize.height + 10); // score m_lbScore = CCLabelBMFont::create("Score:0", s_arial14_fnt); m_lbScore->setAnchorPoint(ccp(1, 0)); m_lbScore->setAlignment(kCCTextAlignmentRight); addChild(m_lbScore, 1000); m_lbScore->setPosition(winSize.width - 5, winSize.height - 30); // ship life CCTexture2D *shipTexture = CCTextureCache::sharedTextureCache()->addImage(s_ship01); CCSprite *life = CCSprite::createWithTexture(shipTexture, CCRectMake(0, 0, 60, 38)); life->setScale(0.6); life->setPosition(ccp(30,winSize.height-23)); addChild(life, 1, 5); // ship life count char lifecount[2]; sprintf(lifecount, "%d",Config::sharedConfig()->getLifeCount()); m_lifeCount = CCLabelTTF::create(lifecount, "Arial", 20); m_lifeCount->setPosition(ccp(60, winSize.height-20)); m_lifeCount->setColor(ccc3(255,0, 0)); addChild(m_lifeCount, 1000); // ship m_ship = Ship::create(); addChild(m_ship, m_ship->getZoder(), 1001); CCMenuItemImage *pause = CCMenuItemImage::create("pause.png", "pause.png", this, menu_selector(GameLayer::doPause)); pause->setAnchorPoint(ccp(1, 0)); pause->setPosition(ccp(winSize.width, 0)); CCMenu *menu = CCMenu::create(pause, NULL); menu->setAnchorPoint(ccp(0, 0)); addChild(menu, 1, 10); menu->setPosition(CCPointZero); // 调 update函数 scheduleUpdate(); // 每秒调一次 scoreCounter函数 schedule(schedule_selector(GameLayer::scoreCounter), 1); if (Config::sharedConfig()->getAudioState()) { SimpleAudioEngine::sharedEngine()->playBackgroundMusic(s_bgMusic, true); } return true; } void GameLayer::update(float dt) { if (m_state == statePlaying) { checkIsCollide(); removeInactiveUnit(dt); checkIsReborn(); updateUI(); } } void GameLayer::scoreCounter() { if (m_state == statePlaying) { m_time++; m_levelManager->loadLevelResource(m_time); } } void GameLayer::checkIsCollide() { CCObject *units; CCObject *bullets; CCObject *enemybs; CCARRAY_FOREACH(enemy_items, units) { UnitSprite *enemy = dynamic_cast<UnitSprite*>(units); CCARRAY_FOREACH(play_bullet, bullets) { UnitSprite *bullet = dynamic_cast<UnitSprite*>(bullets); if (this->collide(enemy, bullet)) { enemy->hurt(); bullet->hurt(); } if (!(m_screenRec.intersectsRect(bullet->boundingBox()))) { bullet->destroy(); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值