为什么java飞机大战实验报告老报停止

用3.0实现飞机大战----通过截屏实现暂停功能|皂荚花
有朋自远方来不亦乐乎!
程序不是看出来的,是写出来的!思想不是想出来的,是敲出来的!欢迎加群交流技术问题!
热度:1,416
暂停功能的做法有很多,拿我原来的例子来说吧,是弹出一个层,然后这个层屏蔽了下层的触摸事件,然后在这个层上实现一些逻辑,这个也是一般暂停功能的做法。或者你可以直接使用pause函数,但是这样做的话触摸是不能屏蔽的,就会导致一个bug使游戏不完善。今天为了玩下截屏,我用这个来做一个暂停功能,熟悉一下3.0的RenderTexture的用法。原理是这样的,当玩家按下了暂停按钮的时候我们截取一下当前场景的屏幕,把图片保存起来,然后跳转到一个新的场景,在这个场景中添加上刚才保存的图片,再添加一个恢复按钮,为了美观还可以添加一些其他的动画,按下恢复按钮弹出刚才的场景,这样做最后是可以实现的,但是要注意在新场景中的东西不要太多,因为旧的场景是push到栈中的,太多游戏就卡了。在使用renderTexture的过程中,真是遇到了不少的问题,比如截取了图片在切换新场景以后报错说是没有这张图片,原因有俩个,一个是3.0截屏需要在截完屏的下一帧才能处理RenderTexture,这样的话在这一帧就切换场景的话肯定是不行的,另一个是路径不对,这个问题使用FileUtils来解决。最后还有一个问题是第一次暂停完全是ok的,以后暂停的话使用的却是第一次用的图片,这是因为第一次使用了图片以后就放在了缓存中了,下次用的时候直接会从缓存中取,这样的话虽然截屏的图片改变了但是用的却是原来的图片,解决方法是改变图片的文件名,新场景使用的图片文件名,每次都不同,但是原来的文件记得要删除,否则就占用了太多的磁盘空间了。好了说了这么多,看代码吧!
#ifndef _UILAYER_H_
#define _UILAYER_H_
#include &cocos2d.h&
//暂停场景
#include &Pause.h&
USING_NS_CC;
class UILayer : public Layer
UILayer(void);
~UILayer(void);
bool init();
CREATE_FUNC(UILayer);
//按钮的回调函数
void menuCallback(Ref * ref);
#include &UILayer.h&
UILayer::UILayer(void)
UILayer::~UILayer(void)
bool UILayer::init()
if(!Layer::init())
auto size = Director::getInstance()-&getWinSize();
//从xml文件中读取中文显示出来
auto dictionary = Dictionary::createWithContentsOfFile(&font/text.xml&);
auto score_label = Label::createWithTTF(((__String *)(dictionary-&objectForKey(&score&)))-&getCString(),&font/DFPShaoNvW5-GB.ttf&,40);
score_label-&setPosition(score_label-&getContentSize().width/2,
size.height-score_label-&getContentSize().height/2);
this-&addChild(score_label);
//添加游戏暂停和开始的开关菜单
auto toggle1 = MenuItemImage::create();
toggle1-&setNormalSpriteFrame(SpriteFrameCache::getInstance()-&getSpriteFrameByName(&pause_button.png&));
auto toggle2 = MenuItemImage::create();
toggle2-&setNormalSpriteFrame(SpriteFrameCache::getInstance()-&getSpriteFrameByName(&resume_button.png&));
auto menuToggle = MenuItemToggle::createWithCallback(CC_CALLBACK_1(UILayer::menuCallback,this),toggle1,toggle2,NULL);
//刚开始设置选择的index是0,如果点击了暂停设置index为1,toggle中的index是从0开始的,第一个添加进去的
//item的index为0
menuToggle-&setSelectedIndex(0);
auto menu = Menu::create(menuToggle,NULL);
menu-&setPosition(Point(size.width*0.95,size.height*0.97));
this-&addChild(menu);
void UILayer::menuCallback(Ref * ref)
auto toggle = (MenuItemToggle *)
//根据用户选择的不同做不同的处理,刚开始我们设置的时候是0,一点击系统就进行了切换,将index设置为了1
if(toggle-&getSelectedIndex() == 1)
//可以直接使用pause方法暂停当前的场景,但是这样做有一个bug,就是不能够屏蔽触摸事件,所以采用截图的方法
//Director::getInstance()-&pause();
/*截取当前场景的图片并且保存*/
auto size = Director::getInstance()-&getWinSize();
//RenderTexture是一个纹理渲染类,我们需要把要渲染的当前场景放进去,这是初始化它的大小
auto render = RenderTexture::create(size.width,size.height);
//开始获取内容
render-&begin();
//是用节点的visit方法加入到渲染中
Director::getInstance()-&getRunningScene()-&visit();
render-&end();
//这里要特别的说明一下,如果保存的文件的名称不变,那在第二次以后暂停的时候用的图片还是第一次的图片
//虽然路径下的图片发生了改变,但是第一次的图片已经放到了缓存中,所以使用如下的方法解决
auto index = UserDefault::getInstance()-&getIntegerForKey(&index&,0);
UserDefault::getInstance()-&setIntegerForKey(&index&,index+1);
auto str = __String::createWithFormat(&pause%d.png&,index);
//我们每次截图都改变了图片的名称,这样在设备上会有很多的图片,所以要把之前的图片删除掉
if(index != 0)
auto str = __String::createWithFormat(&pause%d.png&,index-1);
auto fullPath = FileUtils::getInstance()-&getWritablePath() + str-&getCString();
if(FileUtils::getInstance()-&isFileExist(fullPath))
remove(fullPath.c_str());
//保存图片为PNG格式,当我们想要获取这个文件的时候使用
//FileUtils::getInstance()-&getWritablePath() + &pause.png&;,通过这个方法就可以取得我们保存的图片啦
render-&saveToFile(str-&getCString(),Image::Format::PNG);
//对声音的处理
// SimpleAudioEngine::getInstance()-&pauseBackgroundMusic();
//3.0截屏需要在截完屏的下一帧才能处理RenderTexture,这点要注意
auto _schedule = this-&getScheduler();
auto replaceScene = [](float tm)
//最后切换场景
Director::getInstance()-&pushScene(Pause::createScene());
_schedule-&schedule(replaceScene, this, 0.0f,0,0.0f, false, &screenshot&);
toggle-&setSelectedIndex(0);
#ifndef _PAUSE_H_
#define _PAUSE_H_
#include &cocos2d.h&
USING_NS_CC;
class Pause : public Layer
Pause(void);
~Pause(void);
bool init();
static Scene * createScene();
CREATE_FUNC(Pause);
#include &Pause.h&
Pause::Pause(void)
Pause::~Pause(void)
Scene * Pause::createScene()
auto scene = Scene::create();
auto layer = Pause::create();
scene-&addChild(layer);
bool Pause::init()
if(!Layer::init())
auto size = Director::getInstance()-&getWinSize();
auto index = UserDefault::getInstance()-&getIntegerForKey(&index&);
auto str = __String::createWithFormat(&pause%d.png&,index-1);
//CCFileUtils::sharedFileUtils()-&getWritablePath();提供了一个可以存储的路径
auto fullPath = FileUtils::getInstance()-&getWritablePath() + str-&getCString();
//这里把截屏的那张图片做为背景图片
auto background = Sprite::create(fullPath);
background-&setPosition(Point(size.width/2,size.height/2));
this-&addChild(background);
//添加恢复游戏的按钮
auto resume = MenuItemImage::create();
resume-&setNormalSpriteFrame(SpriteFrameCache::getInstance()-&getSpriteFrameByName(&resume_button.png&));
auto callback = [](Ref * ref)
//弹出保存的场景
Director::getInstance()-&popScene();
resume-&setCallback(callback);
auto menu = Menu::create(resume,NULL);
menu-&setPosition(Point(size.width*0.95,size.height*0.97));
this-&addChild(menu);
//loading的动画效果
Vector&SpriteFrame *&
for(int i=0;i&6;i++)
auto str = __String::createWithFormat(&loading_%d.png&,i+1);
auto spriteFrame = SpriteFrameCache::getInstance()-&getSpriteFrameByName(str-&getCString());
vector.pushBack(spriteFrame);
auto animation = Animation::createWithSpriteFrames(vector,0.2f,-1);
auto animate = Animate::create(animation);
//设置用来执行动画的loading图片
auto loading = Sprite::createWithSpriteFrameName(&loading_1.png&);
loading-&setPosition(Point(size.width*0.85,size.height*0.1));
this-&addChild(loading);
loading-&runAction(animate);
2014年十月 &(8)
2014年九月 &(3)
2014年八月 &(7)
2014年七月 &(14)
2014年六月 &(15)
2014年五月 &(19)
2014年四月 &(14)
2014年三月 &(22)
2014年二月 &(59)
2014年一月 &(16)
小广告-翻墙小插件
文章关键字
Powered by

参考资料

 

随机推荐