《急!在线等》我刚开始学习cocos2dx 教程,为啥我打出的visiblesize提示没有定义呢?已经包含了Cocos2d.h了

Cocos2dx 3.0 提高篇(十)资源加载进度条Loading...
本来这篇博文是昨晚就要写的,可是因为今早要去参加考驾照相关的体检,而我最害怕的就是视力没能达到5.0,毕竟这阶段对着屏幕的时间过久。
所以呢,昨晚我几乎没碰电脑,没玩手机,早睡早起。体检顺利通过!
首先,我要说的是:这次我要写的主题是进度条。 额,等等,先收起你手里愤怒的西瓜刀。我也才知道TestCpp也有这个例子啊。不过TestCpp里的只有label的变化,而我的多加了个进度条。
请容我对我的这种手段取个好听的名称:画龙点睛!
恩,步骤如下:
1、创建label和progressTimer;
2、加载资源,每加载一张都调用回调函数;
3、加载完成,进入新的界面。
首先看下头文件:HelloWorld.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
class HelloWorld : public cocos2d::Layer
HelloWorld():m_numSp(20),m_loadedSp(0),loadProgress(NULL){};
static cocos2d::Scene* createScene();
virtual bool init();
void loadingCallback(Object* pSender);//加载一张图片完成后跳转的毁掉函数
void gotoNewLayer();//加载完后的跳转函数
CREATE_FUNC(HelloWorld);
cocos2d::ProgressTimer* loadP//进度条
cocos2d::LabelTTF* percentL//加载进度label
cocos2d::LabelTTF* loadL//显示 loading: 的label
int m_numSp;//要加载的精灵数目,初始化为 20 张
int m_loadedSp;//已加载的精灵数目
#endif // __HELLOWORLD_SCENE_H__
Size visibleSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();
loadLabel = LabelTTF::create("Loading:","Arial",20);//创建显示Loading: 的label
loadLabel->setPosition(Point(visibleSize.width/2-30,visibleSize.height/2+30));
this->addChild(loadLabel,1);
percentLabel = LabelTTF::create("0%","Arial",20);//创建显示百分比的label
percentLabel->setPosition(Point(visibleSize.width/2+35,visibleSize.height/2+30));
this->addChild(percentLabel,2);
auto loadBg = Sprite::create("sliderTrack.png");//进程条的底图
loadBg->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
this->addChild(loadBg,1);
loadProgress = ProgressTimer::create(Sprite::create("sliderProgress.png"));//创建一个进程条
loadProgress->setBarChangeRate(Point(1,0));//设置进程条的变化速率
loadProgress->setType(ProgressTimer::Type::BAR);//设置进程条的类型
loadProgress->setMidpoint(Point(0,1));//设置进度的运动方向
loadProgress->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
loadProgress->setPercentage(0.0f);//设置初始值为0
this->addChild(loadProgress,2);
2、加载图片
//加载20张图片,每加载完一张就调用回调函数:loadingCallback
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld1.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld2.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld3.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld4.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld5.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld6.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld7.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
Director::getInstance()->getTextureCache()->addImageAsync("HelloWorld.png",this,callfuncO_selector(HelloWorld::loadingCallback));
3、图片加载后的回调函数:
void HelloWorld::loadingCallback(Object* pSender)
++m_loadedSp;//每进到这个函数一次,让m_loadedSp + 1
char buf_str[16];
sprintf(buf_str,"%d%%",(int)(((float)m_loadedSp / m_numSp) * 100),m_numSp);
percentLabel->setString(buf_str);//更新percentLabel的值
float newPercent = 100 - ((float)m_numSp - (float)m_loadedSp)/((float)m_numSp/100);//计算进度条当前的百分比
//因为加载图片速度很快,所以就没有使用ProgressTo,
//或者ProgressFromTo这种动作来更新进度条
loadProgress->setPercentage(newPercent);//更新进度条
//图片加载完成后
if(m_loadedSp == m_numSp)
this->removeChild(loadProgress);//将添加的几个对象删除掉
this->removeChild(percentLabel);
this->removeChild(loadLabel);
//加载完既要跳转到gotoNewLayer,在这里可以
//创建新的Scene,新的Layer,或者其他什么乱七八糟的
this->gotoNewLayer();
4、进入新的界面
void HelloWorld::gotoNewLayer()
auto size = Director::getInstance()->getWinSize();
auto sp = Sprite::create("HelloWorld.png");//用之前加载到缓存中的图片,创建一个精灵。
sp->setPosition(Point(size.width/2,size.height/2));
this->addChild(sp,1);
因为代码里注释都写的挺详细的,所以我也就不说太多废话了。
恩,写完了。这篇是下班后加班写的,外面又下了大雨,我要赶紧冲回去吃饭了。风一般的男纸。
尊重原创,转载请注明原址:http://blog.csdn.net/start530?viewmode=contents
您对本文章有什么意见或着疑问吗?请到您的关注和建议是我们前行的参考和动力&&
您的浏览器不支持嵌入式框架,或者当前配置为不显示嵌入式框架。Blue Path 简约iOS7风格智力游戏
Unravel Line 色彩解密游戏
Scribbles Ball 物理弹性游戏
XCode5添加新建类模板(Cocos2dx Template Class for Scene or Layer)
XCode5添加新建类模板(Cocos2dx Template Class for Scene or Layer)
围观5581次
编辑日期: 字体:
5,581 views
猴子原创,欢迎转载。转载请注明: 转载自,谢谢!
因为常用cocos2dx开发游戏,所以每次新建cpp类文件的时候,XCode默认生成的cpp类基本就是一个空文件,每次都要重复实现cocos2dx的基本代码。很麻烦。(虽然我每次都是修改了HelloWorld文件,新建的文件直接copy HelloWorld内容。感觉还是挺麻烦的。)
今天就修改了下类模板,添加了2个cocos2dx的类模板,下面是新建文件的时候,是不是多出了2个类模板。
下面我就说下怎么添加xcode类模板,很简单的。
1、打开Xcode的类模板目录地址:/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/File Templates
2、打开里面C and C++文件,就会看到Xcode的cpp类模板文件。复制一个C++ Class.xctemplate文件夹取名:2dx Scene Class.xctemplate,放在C and C++目录下。
3、修改TemplateInfo.plist(主要修改创建文件时候的描述介绍)
打开2dx Scene Class.xctemplate/TemplateInfo.plist,
修改Description的值为:A C++ class for Cocos2d-x Scene.
4、修改___FILEBASENAME___.h
打开2dx Scene Class.xctemplate/___FILEBASENAME___.h,修改成以下内容:
// ___FILENAME___
// ___PROJECTNAME___
// Created by ___FULLUSERNAME___ on ___DATE___.
//___COPYRIGHT___
#ifndef _____PROJECTNAMEASIDENTIFIER________FILEBASENAMEASIDENTIFIER_____
#define _____PROJECTNAMEASIDENTIFIER________FILEBASENAMEASIDENTIFIER_____
#include "cocos2d.h"
USING_NS_CC;
class ___FILEBASENAMEASIDENTIFIER___ : public Layer
___FILEBASENAMEASIDENTIFIER___();
~___FILEBASENAMEASIDENTIFIER___();
static Scene* createScene();
virtual bool init();
CREATE_FUNC(___FILEBASENAMEASIDENTIFIER___);
void initData();
#endif /* defined(_____PROJECTNAMEASIDENTIFIER________FILEBASENAMEASIDENTIFIER_____) */
12345678910111213141516171819202122232425262728
//// ___FILENAME___// ___PROJECTNAME___//// Created by ___FULLUSERNAME___ on ___DATE___.//___COPYRIGHT___//&#ifndef _____PROJECTNAMEASIDENTIFIER________FILEBASENAMEASIDENTIFIER_____#define _____PROJECTNAMEASIDENTIFIER________FILEBASENAMEASIDENTIFIER_____&#include "cocos2d.h"USING_NS_CC;&class ___FILEBASENAMEASIDENTIFIER___ : public Layer{public:___FILEBASENAMEASIDENTIFIER___();~___FILEBASENAMEASIDENTIFIER___();static Scene* createScene();virtual bool init();CREATE_FUNC(___FILEBASENAMEASIDENTIFIER___);&private:void initData();};&#endif /* defined(_____PROJECTNAMEASIDENTIFIER________FILEBASENAMEASIDENTIFIER_____) */
5、修改___FILEBASENAME___.cpp
打开2dx Scene Class.xctemplate/___FILEBASENAME___.cpp,修改成以下内容:
// ___FILENAME___
// ___PROJECTNAME___
// Created by ___FULLUSERNAME___ on ___DATE___.
//___COPYRIGHT___
#include "___FILEBASENAME___.h"
___FILEBASENAMEASIDENTIFIER___::___FILEBASENAMEASIDENTIFIER___()
___FILEBASENAMEASIDENTIFIER___::~___FILEBASENAMEASIDENTIFIER___()
Scene* ___FILEBASENAMEASIDENTIFIER___::createScene()
auto scene = Scene::create();
auto layer = ___FILEBASENAMEASIDENTIFIER___::create();
scene-&addChild(layer);
bool ___FILEBASENAMEASIDENTIFIER___::init()
if ( !Layer::init() )
initData();
#pragma mark - initData
void ___FILEBASENAMEASIDENTIFIER___::initData()
Size visibleSize = Director::getInstance()-&getVisibleSize();
// add your codes here...
123456789101112131415161718192021222324252627282930313233343536373839404142434445
//// ___FILENAME___// ___PROJECTNAME___//// Created by ___FULLUSERNAME___ on ___DATE___.//___COPYRIGHT___//&#include "___FILEBASENAME___.h"___FILEBASENAMEASIDENTIFIER___::___FILEBASENAMEASIDENTIFIER___(){&}&___FILEBASENAMEASIDENTIFIER___::~___FILEBASENAMEASIDENTIFIER___(){&}&Scene* ___FILEBASENAMEASIDENTIFIER___::createScene(){auto scene = Scene::create();auto layer = ___FILEBASENAMEASIDENTIFIER___::create();scene-&addChild(layer);return scene;}&bool ___FILEBASENAMEASIDENTIFIER___::init(){if ( !Layer::init() ){return false;}initData();return true;}&#pragma mark - initDatavoid ___FILEBASENAMEASIDENTIFIER___::initData(){Size visibleSize = Director::getInstance()-&getVisibleSize();&// add your codes here...&}
ok, 这样就完成了一个类模板的添加。
现在在XCode里面新建一个2dx Scene类看看。是不是已经有默认内容了。
// MyScene.h
// MagicDemo
// Created by LiuYanghui on 13-12-27.
#ifndef __MagicDemo__MyScene__
#define __MagicDemo__MyScene__
#include "cocos2d.h"
USING_NS_CC;
class MyScene : public Layer
MyScene();
~MyScene();
static Scene* createScene();
virtual bool init();
CREATE_FUNC(MyScene);
void initData();
#endif /* defined(__MagicDemo__MyScene__) */
12345678910111213141516171819202122232425262728
//// MyScene.h// MagicDemo//// Created by LiuYanghui on 13-12-27.////&#ifndef __MagicDemo__MyScene__#define __MagicDemo__MyScene__&#include "cocos2d.h"USING_NS_CC;&class MyScene : public Layer{public:MyScene();~MyScene();static Scene* createScene();virtual bool init();CREATE_FUNC(MyScene);&private:void initData();};&#endif /* defined(__MagicDemo__MyScene__) */
// MyScene.cpp
// MagicDemo
// Created by LiuYanghui on 13-12-27.
#include "MyScene.h"
MyScene::MyScene()
MyScene::~MyScene()
Scene* MyScene::createScene()
auto scene = Scene::create();
auto layer = MyScene::create();
scene-&addChild(layer);
bool MyScene::init()
if ( !Layer::init() )
initData();
#pragma mark - initData
void MyScene::initData()
Size visibleSize = Director::getInstance()-&getVisibleSize();
// add your codes here...
123456789101112131415161718192021222324252627282930313233343536373839404142434445
//// MyScene.cpp// MagicDemo//// Created by LiuYanghui on 13-12-27.////&#include "MyScene.h"MyScene::MyScene(){&}&MyScene::~MyScene(){&}&Scene* MyScene::createScene(){auto scene = Scene::create();auto layer = MyScene::create();scene->addChild(layer);return scene;}&bool MyScene::init(){if ( !Layer::init() ){return false;}initData();return true;}&#pragma mark - initDatavoid MyScene::initData(){Size visibleSize = Director::getInstance()->getVisibleSize();&// add your codes here...&}
对应的你可以添加Layer的类模板。方法一样,我就不重复了。
关于文件模板里面的一个预定义变量,介绍下:
ok,还有很多有趣的功能,可以大家自己探索。比如工程模板,插件等等。
本文固定链接:
转载请注明:
作者:Houzi
Write the code. Change the world.
如果您觉得这篇文章有用处,请支持作者!鼓励作者写出更好更多的文章!
您可能还会对这些文章感兴趣!panjunbing 的BLOG
用户名:panjunbing
访问量:489
注册日期:
51CTO推荐博文
本文是看了杨丰盛老师的视频()后个人的一些感悟杨丰盛老师说得非常详细,推荐和我一样的初学者去看一下-------------------------------------------------------------------------------------------AppDelegate类的代码解析applicationDidEnterBackground()这是个当程序进入后台时会调用的程序,有时候玩游戏时突然有一些事情,把游戏最小化,所以在这个函数中我们应该实现暂停的功能,所以这是Hello World程序中实现applicationDidEnterBackground()的代码void&AppDelegate::applicationDidEnterBackground()&{
&&&&CCDirector::sharedDirector()-&stopAnimation();
&&&&//&if&you&use&SimpleAudioEngine,&it&must&be&pause
&&&&//&SimpleAudioEngine::sharedEngine()-&pauseBackgroundMusic();
}applicationWillEnterForeground()这是程序进入前台时调用的程序,当最小化后再重新把游戏打开会调用这个函数,所以该函数应该实现继续游戏的功能,所以这是Hello World程序中实现applicationWillEnterForeground()的代码void&AppDelegate::applicationWillEnterForeground()&{
&&&&CCDirector::sharedDirector()-&startAnimation();
&&&&//&if&you&use&SimpleAudioEngine,&it&must&resume&here
&&&&//&SimpleAudioEngine::sharedEngine()-&resumeBackgroundMusic();
}applicationDidFinishLaunching()这是程序开始运行时调用的函数,下面是Hello World程序中实现applicationDidFinishLaunching()的代码bool&AppDelegate::applicationDidFinishLaunching()&{
&&&&//&initialize&director
&&&&CCDirector*&pDirector&=&CCDirector::sharedDirector();
&&&&CCEGLView*&pEGLView&=&CCEGLView::sharedOpenGLView();
&&&&pDirector-&setOpenGLView(pEGLView);
&&&&//&turn&on&display&FPS
&&&&pDirector-&setDisplayStats(true);
&&&&//&set&FPS.&the&default&value&is&1.0/60&if&you&don't&call&this
&&&&pDirector-&setAnimationInterval(1.0&/&60);
&&&&//&create&a&scene.&it's&an&autorelease&object
&&&&CCScene&*pScene&=&HelloWorld::scene();
&&&&//&run
&&&&pDirector-&runWithScene(pScene);
&&&&return&
}我们知道导演是Cocos2dx中执行一切的开始,所以该函数首先定义了一个导演。然后导演调用的前三个成员都是用来设置FPS,所以我们能在Hello World的左下角中看到FPS接着该函数定义了一个场景(pScene),该场景等于HelloWorldScene中的场景,然后用导演运行这个场景,所以接下来我们就转到HelloWorldScene类中去看看这个场景是怎么实现的HelloWorldScene类的代码解析scene()这是前面在AppDelegate类中applicationDidFinishLaunching()函数中CCScene&*pScene&=&HelloWorld::scene();中的scene,下面我们看看它的代码CCScene*&HelloWorld::scene()
&&&&//&'scene'&is&an&autorelease&object
&&&&CCScene&*scene&=&CCScene::create();
&&&&//&'layer'&is&an&autorelease&object
&&&&HelloWorld&*layer&=&HelloWorld::create();
&&&&//&add&layer&as&a&child&to&scene
&&&&scene-&addChild(layer);
&&&&//&return&the&scene
&&&&return&
}该场景的函数中定义了一个图层,这个图层被加在场景中,所以我们只需要对图层进行操作就可以了init()顾名思义这是初始化的函数bool&HelloWorld::init()
&&&&//////////////////////////////
&&&&//&1.&super&init&first
&&&&if&(&!CCLayer::init()&)
&&&&&&&&return&
&&&&CCSize&visibleSize&=&CCDirector::sharedDirector()-&getVisibleSize();
&&&&CCPoint&origin&=&CCDirector::sharedDirector()-&getVisibleOrigin();
&&&&/////////////////////////////
&&&&//&2.&add&a&menu&item&with&"X"&image,&which&is&clicked&to&quit&the&program
&&&&//&&&&you&may&modify&it.
&&&&//&add&a&"close"&icon&to&exit&the&progress.&it's&an&autorelease&object
&&&&CCMenuItemImage&*pCloseItem&=&CCMenuItemImage::create(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"CloseNormal.png",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"CloseSelected.png",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&this,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&menu_selector(HelloWorld::menuCloseCallback));
pCloseItem-&setPosition(ccp(origin.x&+&visibleSize.width&-&pCloseItem-&getContentSize().width/2&,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&origin.y&+&pCloseItem-&getContentSize().height/2));
&&&&//&create&menu,&it's&an&autorelease&object
&&&&CCMenu*&pMenu&=&CCMenu::create(pCloseItem,&NULL);
&&&&pMenu-&setPosition(CCPointZero);
&&&&this-&addChild(pMenu,&1);
&&&&/////////////////////////////
&&&&//&3.&add&your&codes&below...
&&&&//&add&a&label&shows&"Hello&World"
&&&&//&create&and&initialize&a&label
&&&&CCLabelTTF*&pLabel&=&CCLabelTTF::create("Hello&World",&"Arial",&24);
&&&&//&position&the&label&on&the&center&of&the&screen
&&&&pLabel-&setPosition(ccp(origin.x&+&visibleSize.width/2,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&origin.y&+&visibleSize.height&-&pLabel-&getContentSize().height));
&&&&//&add&the&label&as&a&child&to&this&layer
&&&&this-&addChild(pLabel,&1);
&&&&//&add&"HelloWorld"&splash&screen"
&&&&CCSprite*&pSprite&=&CCSprite::create("HelloWorld.png");
&&&&//&position&the&sprite&on&the&center&of&the&screen
&&&&pSprite-&setPosition(ccp(visibleSize.width/2&+&origin.x,&visibleSize.height/2&+&origin.y));
&&&&//&add&the&sprite&as&a&child&to&this&layer
&&&&this-&addChild(pSprite,&0);
&&&&return&
}在这个函数中,我们看到了首先添加了一个CCMenuItemImage的按钮,这是Hello World程序中的关闭按钮,按下按钮是会调用menuCloseCallback成员函数,然后用pCloseItem-&setPosition来设置按钮的位置的,最后再用this-&addChild(pMenu,&1)来把它添加到场景中。然后,该函数添加了一个&CCLabelTTF,这是Hello World程序中显示在程序中间的那一行字,同样的,用setPosition设置位置,用this-&addChild来把它添加到场景中最后,该函数还添加了一个CCSprite,这个精灵就是Hello World程序中的背景图片,用setPosition设置位置,用this-&addChild来把它添加到场景中//addChild第二个参数是添加层的意思,比如我添加了一个精灵在1,然后又添加一个在0,那么层数在1的精灵在相同的位置就会覆盖层数是0的精灵menuCloseCallback(CCObject* pSender)这个成员函数是但按下关闭按钮时调用的,所以他应该实现关闭程序的功能void&HelloWorld::menuCloseCallback(CCObject*&pSender)
#if&(CC_TARGET_PLATFORM&==&CC_PLATFORM_WINRT)&||&(CC_TARGET_PLATFORM&==&CC_PLATFORM_WP8)
CCMessageBox("You&pressed&the&close&button.&Windows&Store&Apps&do&not&implement&a&close&button.","Alert");
&&&&CCDirector::sharedDirector()-&end();
#if&(CC_TARGET_PLATFORM&==&CC_PLATFORM_IOS)
&&&&exit(0);
}―――――――――――――――――――――――――――――――――――――――――――――cocos2dx中各层次调用关系:Director(导演)-&Scene(场景)-&Layer(图层)-&Sprite(精灵)导演只有一个,导演可以调用多个场景,场景中可以有多个图层,图层中也可以有多个精灵,图层中也可以有多个子图层,精灵可以不经过图层直接加在场景中。
了这篇文章
类别:未分类┆阅读(0)┆评论(0)2087人阅读
(头注:Cocos2d-x3.2引擎已经集成了MP4播放功能了,本篇文章写于2.x版本)
游戏需要播放mp4文件展示游戏背景,在网上搜了好久,IOS平台比较容易实现,Android就不敢恭维了;
播放mp4需要分平台实现,悲催的是IOS和Android的原生开发都没有做过,所以只能从网上找资料;
目前实现的功能播放,跳过和播放完成之后回到游戏,IOS和Android一样都已经实现;
1、IOS实现:
首先,参考文章:,我是完全按照这篇文章的介绍做的,里面有源代码地址,相信各位了看了之后就回明白,至少也有方向了;
LHVideoPlayerImplCpp.h/mm // cocos2dx中使用的播放MP4接口
LHVideoPlayerImpl.h/m // videoPlayer的oc接口
LHVideoPlayer.h/m // videoPlayer的实现,调用MPMoviePlayerController播放MP4
LHVideoOverlayView.h/m // videoPlayer的上层操作层,有跳过影片按钮。我就功能点而言,介绍其中的两个类。
第一个是LHVideoPlayerImplCpp.h/mm文件,这个是负责给2dx调用的。该类有两个静态方法:
class LHVideoPlayerImplCpp {
* 开始播放MP4视频
* name 视频名称,不要带后缀&.mp4&。(比如文件是test.mp4, 那么name就传&test&)
* frameRect 视频显示的区域。全屏(Rect(0, 0, visibleSize.width, visibleSize.height))
static void playMP4WithName(const char* name, cocos2d::Rect frameRect);
* 设置跳过影片按钮title,默认无跳过影片功能
static void setSkipTitle(const char* title);
};第二个是LHVideoPlayer.h/m,这个是负责播放MP4。
a、这个方法是播放MP4。注释很清楚。
- (void)playMP4WithName: (NSString *)name VideoFrame:(CGRect)rect
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
// 获取视频文件的名称
NSString *url = [[NSBundle mainBundle]pathForResource:name ofType:@&mp4&];
// 初始化player
_player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url]];
[keyWindow.rootViewController.view addSubview: [_player view]];
// 设置player样式
[_player setControlStyle: MPMovieControlStyleNone];
[[_player view] setFrame: rect];
// 当MP4完成播放的回调
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification object:_player];
// 开始播放影片
[_player play];
// 上层操作层
_videoOverlayView = [ [LHVideoOverlayView alloc] initWithFrame: rect];
[keyWindow.rootViewController.view addSubview: _videoOverlayView];
}b、这个方法是播放结束之后,移除播放view。
- (void)removePlayer:(MPMoviePlayerController*)player
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player];
[player.view removeFromSuperview];
[_player release];
[_videoOverlayView removeFromSuperview];
[_videoOverlayView release];
_videoOverlayView =
3、播放完成,通知外界。playerPlayFinished 这个方法是空的,没有通知外界。我看了下,感觉没什么需要,所以没加。(原作者没加,不过考虑到我播放的mp4是挂在一个layer里面实现的,所以还是希望在播放结束的时候该layer能知道;所以,我另外添加了一个函数):
bool LHVideoPlayerImplCpp::getFinshState() {
return [LHVideoPlayerImpl getFinshState];
}至于里面调用的函数就不写了,用于获取视频已经播放结束,然后在layer的visit里面处理:
void ShowMovieStart::visit() {
GUILayer::visit();
bool isfinish =
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
isfinish = LHVideoPlayerImplCpp::getFinshState();
if (isfinish) {
CCLog(&视频播放结束了&);
//做相关处理
}注意看ios实现的部分,当视频结束时,做相关处理;
使用方法:
a、导入头文件
#include “LHVideoPlayerImplCpp.h”b、开始调用接口,假设你要播放的是“loading.mp4”
Size visibleSize = Director::getInstance()-&getVisibleSize();
LHVideoPlayerImplCpp::playMP4WithName(“loading”, Rect(0, 0, visibleSize.width, visibleSize.height));
LHVideoPlayerImplCpp::setSkipTitle(“Skip”);c、影片结束之后,会自动移除视图;
IOS实现相对于Android来说比较容易,而且上诉源代码还提供了跳过功能,非常不错;
2、Android部分,这个比较复杂,一开始我根本不知道从何下手,只能从网上找,但是相关资料也不是很多,而且大多数不容易解决问题,有些可能是写给Android老手看的,像我Android开发只见皮毛者完全云里雾里,不过,看得资料多了,代码还是可以理解的,虽然有时候一知半解,但还是一步步实现了;之前只用过C++和脚本,lua Js什么的,java代码也没写过,不过语言从来不是问题,主要的是原理。
a、首先,如何把mp4播放出来;
视频播放Veiw实现VideoView.java文件:
import java.io.FileD
import java.io.IOE
import android.app.A
import android.content.res.AssetFileD
import android.media.MediaP
import android.net.U
import android.util.L
import android.view.MotionE
import android.view.SurfaceH
import android.view.SurfaceV
import android.view.V
public class VideoView extends SurfaceView implements
SurfaceHolder.Callback,
View.OnTouchListener,
MediaPlayer.OnPreparedListener,
MediaPlayer.OnErrorListener,
MediaPlayer.OnInfoListener,
MediaPlayer.OnCompletionListener {
private static final String TAG = &VideoView&;
private MediaPlayer mPlayer =
private Activity gameA
private Uri resU
private AssetFileD
private boolean surfaceC
private OnFinishListener onFinishL
public VideoView(Activity context) {
super(context);
this.gameActivity =
final SurfaceHolder holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
setOnTouchListener(this);
if (mPlayer != null) {
mPlayer.reset();
mPlayer.release();
mPlayer = new MediaPlayer();
mPlayer = new MediaPlayer();
mPlayer.setScreenOnWhilePlaying(true);
mPlayer.setOnPreparedListener(this);
mPlayer.setOnCompletionListener(this);
mPlayer.setOnErrorListener(this);
mPlayer.setOnInfoListener(this);
//不应该在这里设置holder
//mPlayer.setDisplay(holder);
//mPlayer.prepareAsync();
public VideoView setOnFinishListener(OnFinishListener onFinishListener) {
this.onFinishListener = onFinishL
public void setVideo(Uri resUri) {
this.resUri = resU
mPlayer.setDataSource(gameActivity, resUri);
} catch (Exception e) {
public void setVideo(AssetFileDescriptor fd) {
mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
} catch (IOException e) {
e.printStackTrace();
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
public void surfaceCreated(final SurfaceHolder holder) {
Log.i(TAG, &surfaceCreated&);
surfaceCreated =
mPlayer.setDisplay(holder);
mPlayer.prepare();
} catch (Exception e1) {
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i(TAG, &surfaceDestroyed&);
surfaceCreated =
if(mPlayer != null){
mPlayer.stop();
mPlayer.reset();
public void onPrepared(MediaPlayer player) {
Log.i(TAG, &onPrepared&);
int wWidth = getWidth();
int wHeight = getHeight();
int vWidth = mPlayer.getVideoWidth();
int vHeight = mPlayer.getVideoHeight();
float wRatio = (float) vWidth / (float) wW //
float hRatio = (float) vHeight / (float) wH //
float ratio = Math.max(wRatio, hRatio); //
vWidth = (int) Math.ceil((float) vWidth / ratio); //
vHeight = (int) Math.ceil((float) vHeight / ratio); //
getHolder().setFixedSize(vWidth, vHeight);
mPlayer.seekTo(posttion);
mPlayer.start();
private void dispose() {
mPlayer.release();
if (fd != null) {
fd.close();
} catch (IOException e) {
e.printStackTrace();
public void onCompletion(MediaPlayer mp) {
Log.i(TAG, &onCompletion&);
dispose();
if(onFinishListener != null)
onFinishListener.onVideoFinish();
public boolean onInfo(MediaPlayer mp, int what, int extra) {
public boolean onError(MediaPlayer mp, int what, int extra) {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
//不响应点击事件
public void stop() {
mPlayer.stop(); //
dispose();
if(onFinishListener != null) {
onFinishListener.onVideoFinish();
public void pause() {
posttion = mPlayer.getCurrentPosition();
mPlayer.pause();
public void resume() {
if(surfaceCreated){
mPlayer.start();
if(resUri != null)
mPlayer.setDataSource(gameActivity, resUri);
else if (fd != null) {
mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
} catch (Exception e) {
public interface OnFinishListener {
public void onVideoFinish();
主要用到MediaPlayer来实现,至于MediaPlayer怎么用,我刚开始也不大懂,从网上找资料,很多,有兴趣google之,这里实现了一个视频播放的主要功能,另外有停止(跳过)的功能;
下面是PlayeVideo文件:
import java.io.*;
import org.cocos2dx.lib.Cocos2dxA
import mon.VideoView.OnFinishL
import android.content.res.AssetFileD
import android.net.U
import android.os.B
import android.util.L
import android.view.V
import android.view.ViewG
import android.view.View.OnClickL
import android.widget.B
import android.widget.LinearL
import android.widget.RelativeL
import android.widget.T
import android.content.C
import android.view.LayoutI
public class playvideo implements OnFinishListener {
ViewGroup viewgroup =
private static playvideo pv =
private static XXXX instance =
VideoView videoV
boolean isvideofinished =
//跳过按钮的view
private View layout =
//跳过按钮
private Button skipbtn =
public static playvideo shareInstance() {
if(null == pv) {
pv = new playvideo();
public void ShowVideo(String name) {
System.out.println(&Android ShowVideo 111111&);
if (null == instance) {
Log.i(&&, &name=& + name);
videoView = new VideoView(instance);
videoView.setOnFinishListener(this);
viewgroup = (ViewGroup)instance.getWindow().getDecorView();
AssetFileDescriptor afd = instance.getAssets().openFd(name);
videoView.setVideo(afd);
} catch (IOException e) {
e.printStackTrace();
viewgroup.addView(videoView);
videoView.setZOrderMediaOverlay(true);
//加一个新的界面
Context mContext = ShenMoJie.getContext();
//LAYOUT_INFLATER_SERVICE表示从xml文件中加载布局
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = inflater.inflate(R.layout.video, null);
//添加一层
viewgroup.addView(layout);
//找到对应的按钮
skipbtn = (Button)layout.findViewById(R.id.skipbutton);
skipbtn.setOnClickListener(listener);
//用相对布局定义控件的位置
int width = instance.getWindowManager().getDefaultDisplay().getWidth();
int height = instance.getWindowManager().getDefaultDisplay().getHeight();
System.out.println(&width: &+width+&height: &+height);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)skipbtn.getLayoutParams();
//left, top, right, bottom
params.setMargins(width*5/6, 10, 0, 0);// 通过自定义坐标来放置你的控件
skipbtn.setLayoutParams(params);
private OnClickListener listener = new OnClickListener() {
public void onClick(View v) {
Button btn=(Button)v;
System.out.println(&Android listener&);
switch (btn.getId()) {
case R.id.skipbutton:
System.out.println(&Android listener-&skipbutton&);
skipVideo();
public static void playVideo(final String name) {
System.out.println(&Android playVideo 111111&);
if (instance != null ) {
System.out.println(&Android playVideo 22222&);
instance.runOnUiThread(new Runnable() {
public void run() {
System.out.println(&Android playVideo 333333&);
playvideo.shareInstance().ShowVideo(name);
public static boolean isVideoFinished() {
//System.out.println(&Android isVideoFinished&);
return playvideo.shareInstance().
public static void skipVideo() {
playvideo.shareInstance().videoView.stop();
public void onVideoFinish() {
viewgroup.removeView(videoView);
viewgroup.removeView(layout);
videoView =
isvideofinished =
System.out.println(&Android onVideoFinish&);
public static void SetActivity(XXXX ptActivity) {
instance = ptA
其中XXXX是继承之Cocos2dxActivity的实例,用SetActivity方法,将之传进来,播放PlayVideo,传一个视频文件名,这里需要用到JNI,C++调用java函数,网上也是一大堆的资料,知之为知之,不知百度之,再不知谷歌之,然后就可以实现实现游戏的播放了,注意在VideoView中实现了,播放完成之后会将试图从viewgourp中移除;
到这一步还比较简单,由于之前没有做过Android原生开发,所以连怎么添加一个button都不知道(跳过按钮),不过了解了一下之后,还是实现了,虽然代码不知道写得合不合理;
//加一个新的界面
Context mContext = ShenMoJie.getContext();
//LAYOUT_INFLATER_SERVICE表示从xml文件中加载布局
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = inflater.inflate(R.layout.video, null);
//添加一层
viewgroup.addView(layout);
//找到对应的按钮
skipbtn = (Button)layout.findViewById(R.id.skipbutton);
skipbtn.setOnClickListener(listener);
//用相对布局定义控件的位置
int width = instance.getWindowManager().getDefaultDisplay().getWidth();
int height = instance.getWindowManager().getDefaultDisplay().getHeight();
System.out.println(&width: &+width+&height: &+height);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)skipbtn.getLayoutParams();
//left, top, right, bottom
params.setMargins(width*5/6, 10, 0, 0);// 通过自定义坐标来放置你的控件
skipbtn.setLayoutParams(params);详情请看PlayVideo文件,下面是vidio.xml
&?xml version=&1.0& encoding=&utf-8&?&
&LinearLayout xmlns:android=&/apk/res/android& android:orientation=&horizontal& android:layout_width=&fill_parent& android:layout_height=&fill_parent&&
&Button android:text=&@string/video_skip& android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:id=&@+id/skipbutton& /&
&/LinearLayout&就这样,Android版也实现了播放跳过功能;
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:26373次
排名:千里之外
原创:56篇
转载:23篇
文章:10篇
阅读:6351
(4)(10)(14)(11)(13)(5)(1)(3)(2)(1)(1)(2)(1)(1)(10)}

我要回帖

更多关于 cocos2dx 自定义事件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信