为了适应多平台、不同尺寸的设备,或者我们想省去修改一次游戏尺寸就改一次图片的麻烦。我们需要将Cocos2dx上的精灵,按照根据当前的屏幕大小进行拉伸。
虽然上次在《【Cocos2dx】使用CCScale9Sprite拉伸图片》(点击打开链接)介绍过如何在Cocos2dx利用Scale9Sprite进行图片的拉伸,然而,这样做出来的效果是静态的,拉伸之后出来的结果完全是一个不能对其进一步操作的CCScale9Sprite。
如果我们想做出如下的效果,比如每次创建cocos2dx工程之后,资源文件夹Resources都会自带如下的一张480x320的Helloworld.png图片:
然而我们要求的游戏大小是300x240,当然这只是举个例子而已,实际上经常是要在800x600甚至1024x576等大屏手机运行,同时做出《【Cocos2dx】连续滚动的场景》(点击打开链接)的背景滚动效果如下:
这时就不能用CCScale9Sprite,因为根据
来来去去就是2张完全相同的、边缘紧贴图片在不停地交换位置,形成连续滚动的视觉效果的思想,
除了把2只背景精灵放上去以后,还要对其进行进一步操作,
说白了就是非静态。
制作过程如下,新建一个ScaleBackground的cocos2dx工程,如下图,在main.cpp修改游戏运行尺寸之后。
对HelloWorldScene.h进行重点的修改。
首先是HelloWorldScene.h,没什么好讲的就是一大堆声明,删去原版一大堆没有用的代码之后,记得补上一句USING_NS_CC;否则过不了编译。
#include "cocos2d.h" USING_NS_CC;//头文件就用到了CCxx,精灵声明的CCSprite class HelloWorld:public cocos2d::CCLayer { public: virtual bool init(); static cocos2d::CCScene* scene(); CREATE_FUNC(HelloWorld); private: void background_rolling(float delta);//计时器函数 //两只背景精灵,其实就是同一张图片 CCSprite *sprite1; CCSprite *sprite2; };
之后是HelloWorldScene.cpp,
(1)这里在初始化的时候,便已经对精灵缩放,将屏幕缩放的窗口大小的大小,直接套用公式:将精灵横向缩放 到 (屏幕宽度/精灵宽度) 的倍数。
此处屏幕宽度通过CCSize visibleSize=CCDirector::sharedDirector()->getVisibleSize();获取,值得注意的是CCSize visibleSize=CCDirector::sharedDirector()->getVisibleSize();不可以成为全局变量,必须处于每一个类函数中,否则所有setPosition()、getPositionX()的搞出来的数值是负数,我也不知道为什么,反正如果此类成员函数,要用到尺寸,都补上CCSize visibleSize=CCDirector::sharedDirector()->getVisibleSize();声明一下就对了。
而精灵宽度通过spriteX->getTextureRect().getMaxY()来获取
(2)Cocos2dx的计时器的使用请看《【Cocos2dx】计时器的使用,计时器的嵌套,与在计时器中延时执行一段代码》(点击打开链接),这里不再赘述。
(3)两背景同时向左滚动的时候,判断其是否完全离开屏幕,就是判断其中心点是否已经到达 X轴 -屏幕宽度/2 这个位置。之后将其打回到X轴 屏幕宽度+屏幕宽度/2,这个位置,之后还要在后面向前移一个帧的移动速度,是因为实际测试的时候,发现不减ROLLING_SPEED,是会出现一个黑条的间隔的,不知道为什么,补上ROLLING_SPEED就完美了。
#include "HelloWorldScene.h" #define FRAME_TIME 0.05f//每帧时间 #define ROLLING_SPEED 4//滚动速度,这里的4,意为每帧移动的像素值 //场景声明,一字未改 CCScene* HelloWorld::scene() { CCScene *scene=CCScene::create(); HelloWorld *layer=HelloWorld::create(); scene->addChild(layer); return scene; } bool HelloWorld::init() { CCSize visibleSize=CCDirector::sharedDirector()->getVisibleSize();//获取屏幕大小 //精灵声明 sprite1=CCSprite::create("HelloWorld.png"); sprite1->setPosition(ccp(visibleSize.width/2,visibleSize.height/2)); //将精灵缩放到屏幕大小 sprite1->setScaleX(visibleSize.width/sprite1->getTextureRect().getMaxX()); sprite1->setScaleY(visibleSize.height/sprite1->getTextureRect().getMaxY()); this->addChild(sprite1,0); sprite2=CCSprite::create("HelloWorld.png"); sprite2->setPosition(ccp(visibleSize.width+visibleSize.width/2,visibleSize.height/2)); sprite2->setScaleX(visibleSize.width/sprite2->getTextureRect().getMaxX()); sprite2->setScaleY(visibleSize.height/sprite2->getTextureRect().getMaxY()); this->addChild(sprite2,0); this->schedule(schedule_selector(HelloWorld::background_rolling),FRAME_TIME);//开启一个计时器,此计时器每FRAME_TIME执行一次 return true; } void HelloWorld::background_rolling(float delta){//这段代码每FRAME_TIME执行一次 CCSize visibleSize=CCDirector::sharedDirector()->getVisibleSize(); sprite1->setPositionX(sprite1->getPositionX()-ROLLING_SPEED);//向左移动ROLLING_SPEED sprite2->setPositionX(sprite2->getPositionX()-ROLLING_SPEED); if(sprite1->getPositionX()<-visibleSize.width/2){//如果这个背景已经完全移出屏幕 sprite1->setPositionX(visibleSize.width+visibleSize.width/2-ROLLING_SPEED);//打回到最后 } if(sprite2->getPositionX()<-visibleSize.width/2){ sprite2->setPositionX(visibleSize.width+visibleSize.width/2-ROLLING_SPEED); } }