编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

Cocos2d-x项目实践一FlappyBird-屏幕适配

wxchong 2024-09-10 22:46:48 开源技术 7 ℃ 0 评论

在上一节中,我们介绍了程序的入口AppDelegate进行了介绍,并将整个游戏编译通过,在模拟器中运行了起来,但是在模拟器中出现下面这个情况

这一节我们就先来解决这个问题

屏幕适配

首先我们需要了解下面接个概念和定义

FrameSize :实际上就是设备的原始分辨率,就是你买手机的时候其中一项参数就是屏幕的分辨率,这个FrameSize就是这个参数

WinSize:是我们所设定的设计分辨率,一般情况下是有UI设计人员给出的通用背景图的分辨率来确认

VisibleSize:一定小于等于WinSize,即在WinSize范围之内,保持FrameSize宽高比的最大显示区域

ResolutionPolicy::SHOW_ALL:

全部显示,保证内容在屏幕内显示,同样是宽高等比缩放,但缩放比例取小的进行

ResolutionPolicy::NO_BORDER:

无黑边,宽高等比缩放,但缩放的比例按照宽比和高比中大的来进行

ResolutionPolicy::EXACT_FIT

通过拉伸来填满屏幕,宽高比不同,图片无法等比缩放来填充屏幕,图片会扭曲变形

以上的概念我们用当前游戏的实力来讲解

首先我们设定我们的目标分辨率—WinSize,我们这里的WinSize设置多少合适呢。我们找到素材中的两张组合的背景图

第一张是morning.png 分辨率为540X720(宽X高)

第二张是floor.png 分辨率是 840X240 (宽X高)

大家在想为什么要两张图组合成背景,因为我们再游戏效果中,需要下面的floor作为精灵运动起来,上面的背景图则保持静止,所以两张图片组成整个背景效果。

最后我们的游戏背景设定为 540 X 960 (morning 宽X (morning 高+ floor 高))

在AppDelegate中我们通过这段代码设定WinSize

这里我们将分辨率改成了540X960

请注意,这里我们已经将屏幕设置成了竖屏,所以,前面的参数是表示的款,后面的参数表示高。所以我们需要再将前后参数对调,变成下面这样

这下让我们运行起来看看效果,左侧是调整后的界面,整个界面布局的位置关系基本正确了。右侧是之前没有调整时,位置错乱。但现在仍然有问题,可以看出上面的morning和底部的floor没有填充满屏幕,我们现在要通过缩放来让背景填充屏幕,那么我们该怎样进行缩放呢?

大家可以观察到我们的模拟器设备是采用的iPhone5s,大家应该知道iPhone5s的设备分辨率是

640X1136(宽X高),也就是frameSize = 640X1136

我们设定的设计分辨率就是刚才提到的winSize = 540X960

通过这两个分辨率的宽比和高比来设定缩放因子,然后我们通过

setScaleX()

setScaleY()

两个函数来进行缩放的设置

X缩放因子 = frameSize.width/winSize.width = 640/540

Y缩放因子 = frameSize.height/winSize.height = 1136/960

然后通过函数尽行设定

background->setScaleX(X缩放因子);

background->setScaleY(Y缩放因子);

最后执行看看效果,现在就完美适配了

现在我们就可以继续往下面走,进入游戏下面的开发环节

MainLayer代码编写

首先我们介绍当前这个主界面MainLayer

分析这个界面我们可以知道

  • 需要6个精灵作为item,点击item响应事件

  • 顶部有个fruit bird的title,可以用精灵,也可以用label实现

  • 背景的中部和底部floor精灵,底部的精灵需要运动起来

  • 需要播放音乐

  • 需要响应item点击的回调函数

添加六个menuItem到该场景代码实现

MenuItemImage* gameItem = MenuItemImage::create("button/start.png", "button/start_off.png", CC_CALLBACK_1(MainLayer::menuCallBack0, this));

gameItem->setPosition(Vec2(150, 600));

//添加进入游戏的item,设置位置,点击后调用menuCallBack0函数

MenuItemImage* rankItem = MenuItemImage::create("button/rank.png", "button/rank_off.png", CC_CALLBACK_1(MainLayer::menuCallBack1, this));

rankItem->setPosition(Vec2(390, 600));

//添加进入排行榜的item,设置位置,点击后调用menuCallBack1函数

MenuItemImage* setItem = MenuItemImage::create("button/set.png", "button/set_off.png", CC_CALLBACK_1(MainLayer::menuCallBack2, this));

setItem->setPosition(Vec2(150, 450));

//添加进入设置的的item,设置位置,点击后调用menuCallBack2函数

MenuItemImage* helpItem = MenuItemImage::create("button/help.png", "button/help_off.png", CC_CALLBACK_1(MainLayer::menuCallBack3, this));

helpItem->setPosition(Vec2(390, 450));

//添加进入帮助的item,设置位置,点击后调用menuCallBack3函数

MenuItemImage* aboutItem = MenuItemImage::create("button/about.png", "button/about_off.png", CC_CALLBACK_1(MainLayer::menuCallBack4, this));

aboutItem->setPosition(Vec2(150, 300));

//添加进入关于的item,设置位置,点击后调用menuCallBack4函数

MenuItemImage* exitItem = MenuItemImage::create("button/exit.png", "button/exit_off.png", CC_CALLBACK_1(MainLayer::menuCallBack5, this));

//添加退出游戏的item,设置位置,点击后调用menuCallBack5函数

exitItem->setPosition(Vec2(390, 300));

Menu* menu = Menu::create(gameItem,rankItem,setItem,helpItem,aboutItem,exitItem,NULL);

menu->setPosition(Vec2::ZERO);

this->addChild(menu);

//通过以上6个item创建menu,并添加到layer中

顶部fruit bird title实现

effectNode = NodeGrid::create();//创建effectNode节点

this->addChild(effectNode,10);//添加节点至当前layer

Sprite* title = Sprite::create("pic/title.png");//创建title精灵

title->setPosition(Vec2(270, 800));//设置title精灵位置

effectNode->addChild(title,13);//将title精灵添加到effectNode节点,也就实现了添加到当前layer

Director::getInstance()->setDepthTest(false);//设置深度触摸为false

effectNode->runAction(RepeatForever::create(Ripple3D::create(2.0f, Size(32, 24), Vec2(270, 800), 360, 2, 5))); //effectNode重复的ripple3D动作,飘带的效果

背景的中部和底部floor精灵,底部的精灵需要运动起来

int i = random();

if (i%2==0) {

backGround = Sprite::create("pic/morning.png");

}else

{

backGround =Sprite::create("pic/night.png");

}

backGround->setPosition(Vec2(visibleSize.width/2, visibleSize.height/2+120));

this->addChild(backGround,0);//根据随机函数来创建背景精灵,分别为morning和night,

Sprite* floor =Sprite::create("pic/floor.png");

floor->setPosition(Vec2(origin.x, origin.y));

this->addChild(floor);

floor->runAction(RepeatForever::create(Sequence::create(MoveTo::create(0.5, Vec2(-120, 0)),MoveTo::create(0, Vec2(0, 0)) ,NULL)));//创建底部的floor,并执行延时重复动作,在底部一直运动的动态效果

需要播放音乐

bool MainLayer::musicFlag =true;

bool MainLayer::soundFlag =true;

//初始状态,背景音乐和音效的标志都设置为true

if (musicFlag) {

CocosDenshion::SimpleAudioEngine::getInstance()->playBackgroundMusic("sounds/playscene.mp3",true);

}//对标志位进行判断,如果为true就播放背景音乐playBackgroundMusic

需要响应item点击的回调函数

void MainLayer::menuCallBack0(Ref* pSender)

{

initTitle();

sceneManager->goToGameScene();//进入游戏场景,goToGameScene()在场景管理器中实现,下一节我们将先讲到场景管理器

}

void MainLayer::menuCallBack1(Ref* pSender)

{

initTitle();

sceneManager->goToRankBirdScene();进入排行榜场景,goToGameScene()在场景管理器中实现

}

void MainLayer::menuCallBack2(Ref* pSender)

{

initTitle();

sceneManager->goToSetScene();进入设置场景,goToGameScene()在场景管理器中实现

}

void MainLayer::menuCallBack3(Ref* pSender)

{

initTitle();

sceneManager->goToHelpScene();进入帮助场景,goToGameScene()在场景管理器中实现

}

void MainLayer::menuCallBack4(Ref* pSender)

{

initTitle();

sceneManager->goToAboutScene();进入关于场景,goToGameScene()在场景管理器中实现

}

voidMainLayer::menuCallBack5(Ref* pSender)

{

Director::getInstance()->end();//退出游戏,这里一定要加上下面的对于平台的判断,然后exit,否则不会退出程序,这是iOS平台的特殊之处

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

exit(0);

#endif

}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表