Cocos Creator 2D摄像机 [Lv.2] 截图

Posted VermillionTear

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cocos Creator 2D摄像机 [Lv.2] 截图相关的知识,希望对你有一定的参考价值。

目录

摘要

本文在Cocos Creator 2D摄像机 [Lv.1] 小视图所完成的工程的基础上进行修改,并增加截图功能。

环境

  • Cocos Creator 2.4.4

资源

准备工作

  1. Cocos Creator 2D摄像机 [Lv.1] 小视图 所完成的工程。

正式开始

对工程做一些修改

资源管理器
拷贝MiniMapDemo场景,重命名为CaptureScreenDemo
拷贝MiniMapController.js脚本,重命名为CaptureScreenController.js

层级管理器

  1. CaptureScreenController.js脚本,挂载在CaptureScreenController节点上。

之后节点相关的设置请参考工程中的设置,文中不再赘述。

如何互动

截图功能需要通过RenderTexture实现。
将摄像机照到的图像,渲染到RenderTexture上,然后从RenderTexture上读取出图像数据。
我们将通过右键点击,来触发截图功能。

通过RenderTexture + SpriteFrame来实现小视图

创建一个sprite,用来显示小视图,默认的SpriteFrame删除掉。

CaptureScreenController.js中实现功能。

...
let _texture = null		// RenderTexture

cc.Class(
    ...
    properties: 
        ...
        smallView: cc.Sprite, 	// 小视图。
    ,

    onLoad () 
        ...
        _texture = new cc.RenderTexture()
        _texture.initWithSize(_canvasWidth, _canvasHeight, cc.gfx.RB_FMT_S8)
        this.camera.targetTexture = _texture	// 将摄像机的渲染重定向到 RenderTexture 上。

		// spriteFrame 的 texture 指定为 RenderTexture ,
		// 再把 spriteFrame 添加到 smallView 上,
		// 这样摄像机照到的图像就能通过 smallView 显示出来了。
        let spriteFrame = new cc.SpriteFrame()
        spriteFrame.setTexture(_texture)
        this.smallView.spriteFrame = spriteFrame
    , 
	...
);

将节点挂载到脚本对应变量上。

运行起来,看看效果,

小视图怎么这么小,而且还倒过来了。
小视图很小是由于camera.rect发挥的作用。原先是以整个屏幕作为根本,设置的rect。现在将targetTexture定向到了smallView上,由于smallView已经设置了需要的大小,所以重置camera.rect,让其按照默认的位置和尺寸显示就可以了。

显示倒过来的问题,我们可以通过设置smallViewscaleY = -1来解决。
同时还有一点,我们要将smallView的分组设置为brush。反正不能放在default分组里,否则小视图又会被摄像机渲染出来。

运行起来,看看效果,

已经能正常显示了。但是又发现个小问题,小视图边框(黄线)的显示不太正常。
这是由于原先通过camera.rect实现时,小视图边框是通过camera.rect计算出来的。现在通过smallView来显示,我们就需要通过其Node的属性来计算小视图的边框。
CaptureScreenController.js中修改calCameraDisplayRect函数的实现。

calCameraDisplayRect: function () 
        let cameraPos = this.smallView.node.getPosition()	// 根据 smallView 的位置来计算。
        let cameraAnchor = cc.Vec2(this.smallView.node.anchorX, this.smallView.node.anchorX)
        let cameraSize = width: this.smallView.node.width, height: this.smallView.node.height

		// 绘制的矩形以左下角为原点。
        return new cc.Rect(cameraPos.x - cameraAnchor.x * cameraSize.width, 
                        cameraPos.y - cameraAnchor.y * cameraSize.height, 
                        cameraSize.width, 
                        cameraSize.height)
    , 

运行起来,看看效果,

一切都正常了。

截图

CaptureScreenController.js中实现功能。

...
cc.Class(
    ...
    onLoad () 
        ...
        // 鼠标释放事件,通过右键点击鼠标截图。
        this.node.on(cc.Node.EventType.MOUSE_UP, this.onMouseUp, this)
		...
    , 
    ...
    onMouseUp (event) 
        let mouseType = event.getButton()

        if (mouseType === cc.Event.EventMouse.BUTTON_RIGHT) 	// 鼠标右键释放。
            this.captureScreen()	// 截图。
        
    , 
    ...
    captureScreen () 
        this.camera.render()	// 手动渲染摄像机。

        let picData = _texture.readPixels()		// 从 RenderTexture 中读取图像数据。
        // 图像默认 Y 轴是颠倒的,需要翻转一下 Y 轴。
        picData = this.filpYImage(picData, _texture.width, _texture.height)
        this.saveFile(picData)	// 存储图像。
    , 

    saveFile (picData) 
        if (CC_JSB) 
	        // 存储到可写路径下。
            let filePath = jsb.fileUtils.getWritablePath() + 'render_to_sprite_image.png'

			// 存储图像。
            let success = jsb.saveImageData(picData, _texture.width, _texture.height, filePath)
            if (success) 
                cc.log("save image data success, file: " + filePath)
            
            else 
                cc.error("save image data failed!")
            
        
    , 

    // This is a temporary solution
    filpYImage (data, width, height) 
        // create the data array
        let picData = new Uint8Array(width * height * 4)	// 每个像素 4 字节。
        let rowBytes = width * 4
        for (let row = 0; row < height; row++) 
            let srow = height - 1 - row
            let start = srow * width * 4	// 从最后一行开始递减。
            let reStart = row * width * 4	// 从第一行开始递增。
            // save the piexls data
            for (let i = 0; i < rowBytes; i++) 
                picData[reStart + i] = data[start + i]
            
        
        return picData
    , 
)

运行起来,看看效果,

成功生成了截图文件。

划重点

  • 通过RenderTexture + SpriteFrame来实现小视图。
  • Camera.render() -> RenderTexture.readPixels() -> filpYImage() -> jsb.fileUtils.getWritablePath() -> jsb.saveImageData()

以上是关于Cocos Creator 2D摄像机 [Lv.2] 截图的主要内容,如果未能解决你的问题,请参考以下文章

Cocos Creator 2D摄像机 [Lv.2] 截图

Cocos Creator 2D摄像机 [Lv.1] 小视图

Cocos Creator 2D摄像机 [Lv.1] 小视图

Cocos Creator 2D摄像机 [Lv.1] 小视图

Cocos Creator 2D摄像机 [Lv.1] 小视图

Cocos Creator 热更新 [Lv.2]