功能需求:

1. 之前有videoplayer的使用 不影响之前的功能
2. cocos组件 需要显示到视频上边 
3. android/ios/web 端实现
4. cocos creater 版本 2.1.3

参考链接:
https://worthatry.cn/cocos-creator-ru-he-shi-bei-jing-tou-ming/

设计思路:

不影响原来的加载实现
添加新的方法调用 swapUpToCanvas 在不修改原来代码的基础上。新写的代码手动调用swapUpToCanvas 使视频控件切换到 canvas 下边

方案实现:

cocos js代码修改:

		// 可以添加到 main.js 游戏启动之前 
		// 也可以添加到 第一个场景 的js 文件中
		// 开启cocos creater 的canvas 支持透明
        cc.macro.ENABLE_TRANSPARENT_CANVAS = true;

cocos scene 设置

  1. 场景camera设置 opaque属性为true
    在这里插入图片描述
  2. 设置 camera 的backgroundColor 的alpha为0
    在这里插入图片描述

web端代码修改

		// 在VideoPlayerImpl 基类里边添加如下方法
		swapUpToCanvas:function swapUpToCanvas(){
            this._video && (this._video.style.zIndex = -1);
      	},

安卓端代码修改

  1. 为了不影响旧代码的效果 我们不需要修改 Cocos2dxVideoHelper.java (如果没有上下切换的需求 可以直接设置取消置顶)
	private void _createVideoView(int index) {
        Cocos2dxVideoView videoView = new Cocos2dxVideoView(mActivity,index);
        sVideoViews.put(index, videoView);
        FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.WRAP_CONTENT,
                FrameLayout.LayoutParams.WRAP_CONTENT);
        mLayout.addView(videoView, lParams);
        // 设置 video 置顶。 如果没有切换video 层级的需求 可以直接注释这句
        videoView.setZOrderOnTop(true);
        videoView.setVideoViewEventListener(videoEventListener);
    }
  1. 修改 AppActivity.java 文件 设置渲染支持透明通道
	public Cocos2dxGLSurfaceView onCreateView() {
        //Log.e("--- cccccc ---", "onCreateView 111");
        Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
        // TestCpp should reate stencil buffer
        // glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);
	
		// 设置支持透明通道
        glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8);
        glSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);
        glSurfaceView.setZOrderMediaOverlay(true);

        return glSurfaceView;
    }
  1. 修改 Cocos2dxVideoView.java 文件 解除原始videoPlayer 控件的点击拦击
	public boolean onTouchEvent(MotionEvent event) {
        if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
            this.sendEvent(EVENT_CLICKED);
        }
        // return true;
        return false; 		// 因为video 显示到canvas下边了。所以没必要拦截点击 
    }
  1. 修改 Cocos2dxVideoHelper.java 添加方法swapUpToCanvas
	// 备注 这里只写了实现方式。 具体js调用java方法 请参考: _startVideo / _pauseVideo / _stopVideo 等其余引擎代码的实现。
	private void swapUpToCanvas(int index) {
        Cocos2dxVideoView view = sVideoViews.get(index);
        Log.d("cocosswap", "swapUpToCanvas: start");
        if (view != null) {
            Log.d("cocosswap", "swapUpToCanvas: success");
            view.setZOrderOnTop(false);
        }
    }

ios端代码的修改:

  1. 修改CCApplication-ios.mm 渲染格式 支持透明通道
void Application::onCreateView(PixelFormat& pixelformat, DepthFormat& depthFormat, int& multisamplingCount)
{
	// 修改渲染格式 支持 透明通道
    pixelformat = PixelFormat::RGBA8;
    depthFormat = DepthFormat::DEPTH24_STENCIL8;

    multisamplingCount = 0;
}
  1. 修改 video 添加到 canvas 窗口下边
  • 2.1 方法1 直接把cocos 的窗口的父节点创建一个两个节点。一层显示video 一层显示cocos(这种方式 调起照相机的时候 opengl会报错 具体原因未知)
// AppController.mm 文件修改如下内容

	// 先添加videoView再添加cocosView
    UIViewController* rvC = [[UIViewController alloc]init];
    // 视频view
    UIView *videoView = [[UIView alloc] initWithFrame:bounds];
    videoView.tag = 10; // 通过tag找到view
    [rvC.view addSubview:videoView];
    // 引擎view
    UIView *cocosView = _viewController.view;
    cocosView.frame = bounds;//
    cocosView.backgroundColor = [UIColor clearColor];
    [rvC.view addSubview:cocosView];
    
    // Set RootViewController to window
    if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0)
    {
        // warning: addSubView doesn't work on iOS6
         [window addSubview: rvC.view]; //新的rootView
    }
    else
    {
        // use this method on ios6
        [window setRootViewController:rvC]; //新的rootView
    }

// VideoPlayer-ios.mm 代码修改如下内容

// 备注 这里只写了实现方式。 具体js调用oc方法 请参考: play / pause / resume 等其余引擎代码的实现。
-(void)swapUpToCanvas{
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    // cocos 的父节点里 把video 的预设层级取出来 添加video
    [[[eaglview superview] viewWithTag:10] addSubview:self.playerController.view];
}
  • 2.2 方法2 不修改原始 cocos 的结构。 通过 keywindow 获取video节点
// 我们是项目中是 自定义的viewControl.mm里修改 (正常工程应该是 AppController.mm)文件修改如下内容 初始化修改

	UIWindow *alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    alertWindow.windowLevel = UIWindowLevelAlert;
    alertWindow.backgroundColor = HexRGB(0xffa86f);
    alertWindow.rootViewController = self;
    self.view.frame = CGRectMake(0, 0, APP_SCREEN_WIDTH, APP_SCREEN_HEIGHT);
    // 视频view
    UIView *videoView = [[UIView alloc] init];
    videoView.backgroundColor = UIColor.blackColor;
    videoView.tag = 10; // 通过tag找到view
    [alertWindow addSubview:videoView];
    [videoView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.bottom.right.equalTo(alertWindow);
    }];
    self.cocosWindow = alertWindow;
    //--
    self.previousWindow = [UIApplication sharedApplication].keyWindow;
// VideoPlayer-ios.mm 代码修改如下内容

// 备注 这里只写了实现方式。 具体js调用oc方法 请参考: play / pause / resume 等其余引擎代码的实现。
-(void)swapUpToCanvas{
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    [[window viewWithTag:10] addSubview:self.playerController.view];
}

逻辑中 代码 调用swapUpToCanvas

			// 请注意调用时机。如果 不行的话 自行探索一下 我们项目组是这样调用的
			if(this._player.$VideoPlayer && this._player.$VideoPlayer.swapUpToCanvas){
                if (cc.sys.os == cc.sys.OS_IOS){
                	// ios 是 video 实例创建出来以后 才能调用 
                    this.node.runAction(cc.sequence(cc.delayTime(1), cc.callFunc(() => {
                            this._player.$VideoPlayer.swapUpToCanvas()
                        }),
                        cc.delayTime(1),cc.callFunc(() => {
                            this._player.$VideoPlayer.swapUpToCanvas()
                        }),
                        cc.delayTime(1),cc.callFunc(() => {
                            this._player.$VideoPlayer.swapUpToCanvas()
                        }),
                        cc.delayTime(1),cc.callFunc(() => {
                            this._player.$VideoPlayer.swapUpToCanvas()
                        })
                    ))
                } else {
                	// web / android 均可以直接调用 
                    this._player.$VideoPlayer.swapUpToCanvas()
                }
                
            }
        }
        

至此 项目中就可以动态切换 video 和 canvas 的层级了
video 需要在canvas上边 常规写法就可以
video 需要在canvas上边 创建videoPlayer 的时候。调用一下swapUpToCanvas 即可

Logo

这里是一个专注于游戏开发的社区,我们致力于为广大游戏爱好者提供一个良好的学习和交流平台。我们的专区包含了各大流行引擎的技术博文,涵盖了从入门到进阶的各个阶段,无论你是初学者还是资深开发者,都能在这里找到适合自己的内容。除此之外,我们还会不定期举办游戏开发相关的活动,让大家更好地交流互动。加入我们,一起探索游戏开发的奥秘吧!

更多推荐