2017-10-26 15:49:00 weixin_33796205 阅读数 841

 

    我们在使用videoView播放视频时,如果获取内容失败、网址不对、或者视频格式不对等,会弹出“无法播放该视频”的弹窗,阻塞用户使用。

    这种情况,如果在一些自助服务类场合下,弹窗会造成十分不友好的用户体验和观感,例如:自动售卖机的视频广告窗口被弹窗阻塞。

 

    这个时候,我们可以为videoView设置一个播放错误的监听器,如果无法正常播放时,调用该监听器,停止videoview的使用。

videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                videoView.stopPlayback(); //播放异常,则停止播放,防止弹窗使界面阻塞
                return true;
            }
        });

 

2015-01-05 02:18:57 asd131531 阅读数 1032

最近在研究怎么把积分墙嵌入到Cocos2d-x Lua的里,折腾了几天,总算调通了,主要要解决的问题是,调用积分墙之后,当积分发生改变的时候,有一个回调方法,回调会返回用户还剩下多少积分,当Android收到这个回调的时候,需要把这个通知给lua做对应的处理,我就是在这里卡住了。

先理一下思路要实现上面提到的回调通知lua,首先要实现Android回调给C++,再从C++去调用Lua的方法。

一步一步来,先看Android端的回调方法,当有积分变化的时候,onPointBalanceChange方法会被触发:

图片描述

onPointBalanceChange方法里用到了一个pointsBalanceChange()的方法,这个方法在下面被定义成了本地函数,通过本地函数,来调用C++的代码

再看在C++的里的代码:

图片描述

先判断是Android的情况下再进行下一步处理
然后写一个方法,这个方法的方法名图上已经有详细说明了

void Java_org_cocos2dx_lua_AppActivity_pointsBalanceChange( JNIEnv *env,jobject thiz,jint point ){}

到现在为止,不出意外的话,编译应该会通过,并且可以用真机运行调试,当Android里的积分变化回调方法被触发的时候,对应到C++里的方法也会被触发,并且输出CCLog里的内容

如果这一步你调试通了,那就表示从Android到C++的调用调通了,接下来再看C++怎么调用lua,需要在刚才的基础上添加一些配置:

图片描述

1、先添加了:

//把LuaEngine include进来之后,下面会用到这个
#include "CCLuaEngine.h"

2、在Java_org_cocos2dx_lua_AppActivity_pointsBalanceChange方法里添加一大堆东西,我挨个解释一下(有的我也不太明白,有错误请指正)

//这两个我是没太明白,大概意思是得到一个可以和lua连接的对象
auto engine = LuaEngine::getInstance()->getLuaStack();
lua_State *state = engine->getLuaState();
//通过这个方法去查找lua函数,并压入栈底,pointsBalanceChange是在lua定义的一个function
lua_getglobal(state, "pointsBalanceChange");
//pointsBalanceChange需要接受一个参数,这里把Android得到的积分数据,传入给这个function
engine->pushInt(point);
//调用pointsBalanceChange函数,第二个参数表示有多少参数,第三个表示有多少个返回值,第四个参数设置成0表示如果出错了,直接输出原始的错误信息,具体的没太明白,后续在研究
lua_pcall(state, 1, 0, 0);
//调用完成后清栈,第二个参数为从堆栈中弹出的返回值,因为没有返回值所以设置为0
lua_pop(state, 0);  

到这里,C++的代码都写完了,接下来需要在lua下的main.lua里实现一个pointsBalanceChange方法,接受一个参数,在这个方法里输出一下得到的point:

图片描述

都完成了,这个时候编译一下:

cocos compile -p android

不出意外是没问题的,然后真机测试,当Android的回调函数被触发的时候对应的Lua里的cclog日志也被输出出来了:

图片描述

2015-09-30 14:53:58 alex8046 阅读数 0

导语:
首先Cocos2d-x当中实现Menu和Back按键相对简单一点,而在资源较少的Cocos2d-html5当中,要实现返回还是有一点不一样的,而且有没有具体的demo,也就只有自己去看api文档,这也是头痛的一件事情,以下总结和归纳在Cocos2d-html5当中,如何实现返回键,和Menu键。

分析:
cocos2d中目前只有Layer以及其子类能够获取用户输入,即触发用户输入的事件。这个结论是我通过查看API文档猜测的,因为要触发这些事件,必须要有setIsKeypadEnabled和setIsTouchEnabled方法,而API中只有layer和其子类有这两个方法,所以很自然要实现返回必须是在Layer场景或者其子类去实现。

代码:
     
    myLayer.backClicked=function(){
        cc.log("back Clicked");
        cc.AudioEngine.getInstance().stopAllEffects();
        cc.BuilderReader.runScene("", "LevelLayer");
    }
    myLayer.setKeypadEnabled(true);

备注:此方法只适合使用cocosEditord的时候使用,cocos2d-js3.0之后的版本请使用以下的代码
cc.eventManager.addListener({event: cc.EventListener.KEYBOARD,onKeyReleased: function(keyCode, event){
if(keyCode == cc.KEY.back){
}
else if(keyCode == cc.KEY.menu){

}}}, this);

cc.eventManager.addCustomListener(cc.game.EVENT_HIDE, function(){
//onEnterBackground handler
});
cc.eventManager.addCustomListener(cc.game.EVENT_SHOW, function(){
//onEnterForeground handler
});



源引:http://blog.sina.com.cn/s/blog_7dbac1250101pkc7.html

2014-08-12 14:04:01 xiaot01 阅读数 0

Cocos2dx移植到Android平台过程中,需要显示Android提示框,下面说一下我的实现过程

1.C++方面,使用JNI调用Java的函数。关于JNI的知识,百度上有很多,这里不做叙述

2.Java方面,使用AlertDialog创建一个提示框,我用到的是列表框,关于其他提示框的创建,基本大同小异,请自行百度

3.尼玛,全都是自行百度,你到底要说什么

4.列位不要捉急,真正值钱的东西在这呢,往这边看:

5.先附上创建列表框的代码:

static public void showItems()

{

               final String[] m_Items = {"item1","item2"};
               AlertDialog.Builder m_build = new AlertDialog.Builder(sContext);
               m_build.setTitle("请选择类型"); 
               OnClickListener onclick = new DialogInterface.OnClickListener()
                    {
                        public  void onClick(DialogInterface dialog, int which)
                        {
                            Log.i("selectID","SelectID is %d"+which);
                            //MyJavaToCpp.CppCallback("Payment"+ "," + which);

                           // 这里执行你自己的函数
                        }
                    };
                m_build.setItems(m_Items, onclick );                                  
               m_build.show();
}

5.如果你发现,你一调用这个showItems函数,程序就崩溃了,Eclipse报错:Can't create handle inside thread that has not called Looper.prepare() 

6.哦!这样直接调用是不可以的,解决方法如下:

static public void showItems_Pro()

{

      ((Cocos2dxActivity)sContext).runOnUiThread(new Runnable() {  
              public void run() { 

                     showItems()//上面的提示框创建函数

             }  
       }); 

}

2015-12-30 20:43:36 u014486880 阅读数 1944

上一篇我们主要讲了Cocos2d_android一些布置游戏场景的知识,这一篇重点讲下Cocos2d_android的事件触发,没看过上一篇的可以先去看下。

Cocos2d_android你所需要知道的一切

对于本章我做了个demo,完成各种动画。先看下效果图。


点击不同的圣诞树会有不同的动画。因为屏幕有限演示的动画有限,但实现思路都是一样的。

一,Action的简介

Cocos2d_android的CCAction总共有四类子类,它们分别是CCFiniteTimeAction,CCFollow,CCRepeatForever,CCSpeed。它们的含义如下:

CCFiniteTimeAction:表示受时间限制的动作,这可以说是最常见的,因为通常动画都是需要一定时间来完成的。它有两个主要的子类,CCFiniteTimeAction和CCIntervalAction,前者是瞬时动作,后者是延时动作。
CCFollow:表示不受时间限制的动作。
CCRepeatForever:表示序列帧播放,非常常用。
CCSpeed:用于控制游戏的速度。

二,CCIntervalAction常见动作

1.移动
移动是游戏中最常见的动作之一,如植物大战僵尸中的僵尸,子弹等。而Cocos2d中设置移动也很简单,看以下代码:
CGPoint point = CGPoint.ccp(300, 150);
     CCSprite sprite = CCSprite.sprite("bg.img");
     CCMoveTo moveTo = CCMoveTo. action(1, point);
     sprite.runAction(moveTo);
CGPoint.ccp就是初始化一个点,CCMoveTo.action就是就是设置sprite通过1秒的时间移动到point上。很简单吧。最后runAction执行动作。
这里还关系到一个MoveTo和MoveBy的区别。它们的区别有两点:
* 简单说MoveTo就是移动到绝对位置,如上面的例子就是移动到(300,150)这个坐标点,而MoveBy就是相对位置,如果当前位置是(100,0),那执行上面的代码最终会移动到(400,150)的位置上,也就是相对当前位置的(300,150)所在的点。
* MoveBy中有一个reverse()方法,可以让动作反向执行,而MoveTo没有。
MoveBy的代码与MoveTo类似:
CGPoint point = CGPoint.ccp(300, 150);
     CCSprite sprite = CCSprite.sprite("bg.img");
     CCMoveBy moveBy = CCMoveBy. action(1, point);
     sprite.runAction(moveBy);
再看看调用reverse()的情况,具体运动状态可以看我的demo的第四棵树。
CGPoint point = CGPoint.ccp(300, 150);
     CCSprite sprite = CCSprite.sprite("bg.img");
     CCMoveBy moveBy = CCMoveBy. action(1, point);
<pre name="code" class="java" style="font-size: 16px; orphans: 2; widows: 2;">CCMoveBy moveBy1 = moveBy.reverse() ;
sprite.runAction(moveBy);

由于By与To的代码很类似,下文就只贴一种类型的代码了。不然会累死,哈哈。
2.旋转旋转的实现也很简单,与Move类似,看下代码:
CCRotateBy scaleBy = CCRotateBy.action(0.2f, 360);//100是顺时针100度
	sprite.runAction(scaleBy);
第一个参数依然是时间,第二个参数是度数。旋转是顺时针的。可以看demo的第二棵树。
这里By与To又有点不同,To比较懒,如果是大小180度,它会逆时间转,它的原则是尽量少转。By就比较老实,写多少度,它就转多少。
3.缩放
就是缩小放大这个动作,看我demo中的每一棵树,这树的动作并不是一次性的,而是像个心脏似的一起跳,这里就有两个问题,如何让放大缩小两个动作串联起来?如何使动作循环执行?先不急,后面会系统讲解,先带着这问题继续往下。缩放的代码:
CCScaleBy scaleBy = CCScaleBy.action(0.2f, 1.5f);
     sprite.runAction(scaleBy);
4.跳跃
玩过超级玛丽的都知道,小玛丽跳的高度和大玛丽跳的不一样,有些牛X的还能二连跳。其实这个实现起来也很方便,先看一连跳:
CGPoint pos = CGPoint.ccp (300, 150);
            // 跳跃:启动;时间;目标点;高度:实际跳跃的高度(最高点);次数
           CCJumpBy jumpBy = CCJumpBy. action(2, pos, 100, 1);
           CCSprite sprite = getSprite();
           sprite.runAction(jumpBy);
pos指定最终跳到的点,CCJumpBy.action第一个参数是时间,第二个参数是终点,第三个参数是跳到的高度(最高点),最后一个参数是指跳的次数,由此可见,二连跳就很简单了,只要把1修改为2就可以了。
5贝叶斯曲线
这个听起来很高端,其实就是抛物线状。植物大战僵尸里的花吐出的阳光就走了一条抛物线。实现如下:
CCBezierConfig c = new CCBezierConfig();
           c. controlPoint_1 = CGPoint. ccp(0, 0);
           c. controlPoint_2 = CGPoint. ccp(150, 200);
           c. endPosition = CGPoint. ccp(300, 0);
           CCBezierBy bezierBy = CCBezierBy. action(2, c);
           getSprite().runAction(bezierBy);
6.渐快渐慢动作
这个经常用在打斗游戏中,一个怪快速跳到另一个怪身边,杀杀,然后再跳回来,就是一个渐快到渐慢的过程。看下它的代码:
CGPoint pos = CGPoint.ccp (300, 200);
           CCMoveBy moveBy = CCMoveBy. action(2, pos);
           CCEaseIn easeIn = CCEaseIn. action(moveBy, 10);// 渐快:加速运动(加速度恒定)
           CCEaseOut easeOut = (CCEaseOut) easeIn.reverse();
           getSprite().runAction(
                      CCRepeatForever.action(CCSequence.actions(easeIn,
                                CCDelayTime. action(1), easeOut)));
可能上面的代码有几处地方不懂,下面会讲解。先总结下基本的运行方法:
移动动作:CCMoveBy   CCMoveTo
缩放动作:CCScaleBy   CCScaleTo
旋转动作:CCRotateBy   CCRotateTo
跳跃动作:CCJumpBy   CCJumpTo
贝赛尔曲线动作:CCBezierBy   CCBezierTo
淡入淡出动作:CCFadeBy   CCFadeIn   CCFadeOut

三,组合动作

上部分分个讲了一些常见的动作,但真实游戏实现单个动作的比较少,一般都是串在一起实现的。所以组合动作再所难免。先来看几个常用的接口:
CCSequence:用于将多个动作串联到一起。
CCRepeatForever:用于把一个动作循环执行。
CCDelayTime:设置延时时间。
CCSpawn:并行执行动画。
看到这,上面心跳的那个例子就可以实现了,如下:
CCScaleBy scaleBy = CCScaleBy.action(0.2f, 1.5f);
     CCSequence ccSequence = CCSequence. actions(scaleBy, scaleBy.reverse());
     CCRepeatForever ccRepeatForever = CCRepeatForever.action(ccSequence);
     sprite.runAction(ccRepeatForever);
接下来我们用以上几个接口来共同实现一个复杂动作,一棵树翻两个跟斗,具体可以看demo的第三棵树。先看代码:
 // 跳跃:启动;时间;目标点;高度:实际跳跃的高度(最高点);次数
   CCJumpBy jumpBy = CCJumpBy. action(2, pos, 100, 2);
     CCRotateBy scaleBy = CCRotateBy. action(0.2f, 100);//100是顺时针100度
     //并行执行动画
     CCSpawn ccSpawn = CCSpawn. actions(jumpBy, scaleBy);
     //每循环一次停一秒
     CCSequence ccSequence = CCSequence. actions(ccSpawn, ccSpawn.reverse(),CCDelayTime.action(1));
     CCRepeatForever ccRepeatForever = CCRepeatForever.action(ccSequence);
   sprite.setAnchorPoint(0.5F, 0.5F);
   sprite.runAction(ccRepeatForever);
CCSpawn让跳和旋转两个动作同时执行,然后调用CCSequence再串联一个回来的动作,调用CCDelayTime停一秒后,再经CCRepeatForever继续循环执行动作。
到此已经可以完成很多复杂的动画了。在这里问一个问题,如果我想在某个动作结束后执行某个方法,该怎办?这里要强调的是,动画的执行是在多线程的,所以你直接把方法写在动作后面是行不通的。所以要通过CCCallFunc.action(this, "loadInfo")来调用自定义的方法,这里的方法名是loadInfo。代码如下:
CCSequence sequence = CCSequence.actions(CCDelayTime.action(1),
				CCCallFunc.action(this, "loadInfo"));
		sprite.runAction(sequence);
这是1秒后执行loadInfo方法。

四 序列帧播放

什么时序列帧?就是一系列的图片连到一起组成一个动话,就叫序列帧。如一只怪的头点一下,就要有好几张图片串起来实现它的头慢慢下降。先看例子再进行讲解:
           CCSprite bar  = CCSprite.sprite("image/loading/loading_01.png");
           bar.setAnchorPoint( cgSize. width/2, 25);
            this.addChild(bar);
            //以下是序列帧
           List<CCSpriteFrame> frames = new ArrayList<CCSpriteFrame>();
           String fileName = "image/loading/loading_%02d.png" ;//用占位符表示图片尾部,格式为两位数,如01,11。
            for( int i = 1 ;i <= 9;i++){
                CCSprite frame = CCSprite.sprite(String.format(fileName, i));
                frames.add(frame.displayedFrame());
           }
           
           CCAnimation animation = CCAnimation. animation("", 0.2f,(ArrayList<CCSpriteFrame>)frames);
           CCAnimate animate = CCAnimate.action(animation,false);//false表示只加载一次
           bar.runAction(animate);
首先加载初始状态。把一系列的精灵转成CCSpriteFrame格式的转入到CCAnimation中,它就会自动播放。fileName中的%2d是规定了两位,d是点位符,传什么数进来就显示什么。比如,传1,就显示01,传11就显示11。最后CCAnmate.action中的false表示只加载一次,即动画只执行一次。如果要循环执行,就把它改为true。
到这里,基础知识就介绍的差不多了,可以尝试去玩下植物大战僵尸,代码在上一篇博客中提供了。

源码下载