截图是游戏中非常常见的一个功能,在cocos中可以通过摄像机和 RenderTexture 可以快速实现一个截图功能,具体API可参考:https://docs.cocos.com/creator/manual/zh/render/camera.html?h=%E6%88%AA%E5%9B%BE,其中官方也提供了比较完整的例子。

实际上不用官网提供的全屏截图的例子,一般在网页中我们也能将页面截图保存,比如通过htmltocanvas,cocos开发的小游戏在网页中打开实际就是一个canvas,前端是可以通过将canvas保存为图片的,这里就不细说了。

我们还是来看下如何把屏幕中某一区域的内容生成图片并保存到本地。

1、创建RenderTexture

//新建一个 RenderTexture,并且设置 camera 的 targetTexture 为新建的 RenderTexture,这样 camera 的内容将会渲染到新建的 RenderTexture 中。
let texture = new cc.RenderTexture();
let gl = cc.game._renderContext;
//如果截图中不含mask组件可以不加第三个参数,不过建议加上
texture.initWithSize(this.node.width, this.node.height, gl.STENCIL_INDEX8);//这里的宽高直接决定了截图的宽高,如果是全屏截图就是cc.visibleRect.width, cc.visibleRect.height,该处可以设置为截图目标区域的宽高
this.camera = this.node.addComponent(cc.Camera); this.camera.targetTexture = texture; this.texture = texture;

2、绘制canvas

createSprite() {
let width = this.texture.width;
let height = this.texture.height;
     //截图的本质是创建一个canvas,然后通过canvas生成图片材质
if (!this._canvas) {
this._canvas = document.createElement('canvas');
this._canvas.width = width;
this._canvas.height = height;
} else {
this.clearCanvas();
}
let ctx = this._canvas.getContext('2d');
this.camera.render();//相机绘制,将屏幕上的内容更新到renderTexture中
let data = this.texture.readPixels();//读取renderTexture中的数据 let rowBytes = width * 4;
for (let row = 0; row < height; row++) {
let srow = height - 1 - row;
let imageData = ctx.createImageData(width, 1);
let start = srow * width * 4;
for (let i = 0; i < rowBytes; i++) {
imageData.data[i] = data[start + i];
} ctx.putImageData(imageData, 0, row);
}
return this._canvas;
},

上述代码中用到了canvas 的createImageData() 和putImageData()方法,createImageData() 方法创建新的空白 ImageData 对象,putImageData() 方法将图像数据(从指定的 ImageData 对象)放回画布上。

3、获取图片

initImage(img) {
// return the type and dataUrl
var dataURL = this._canvas.toDataURL("image/png");
var img = document.createElement("img");
img.src = dataURL;
return img;
},

生成canvas就可以通过canvas.toDataURL()方法将canvas转换为图片

4、生成截图效果,将上一步生成的图片当做材质挂载到新建的node

showSprite(img) {
let y = this.getTargetArea().y;
let x = this.getTargetArea().x;
let rect = new cc.Rect(x, y, 770, 800)
let texture = new cc.Texture2D();
texture.initWithElement(img); let spriteFrame = new cc.SpriteFrame();
spriteFrame.setTexture(texture);
spriteFrame.setRect(rect) let node = new cc.Node();
let sprite = node.addComponent(cc.Sprite);
sprite.spriteFrame = spriteFrame; node.zIndex = cc.macro.MAX_ZINDEX;
node.parent = cc.director.getScene();
// set position
let width = cc.winSize.width;
let height = cc.winSize.height;
node.x = width / 2;
node.y = height / 2;
node.on(cc.Node.EventType.TOUCH_START, () => {
node.parent = null;
node.destroy();
});
this.captureAction(node, width, height);
},

5、截图动画(类似手机截图,截图后有个缩略图动画)

captureAction(capture, width, height) {
let scaleAction = cc.scaleTo(1, 0.3);
let targetPos = cc.v2(width - width / 6, height / 4);
let moveAction = cc.moveTo(1, targetPos);
let spawn = cc.spawn(scaleAction, moveAction); let finished = cc.callFunc(() => {
capture.destroy();
})
let action = cc.sequence(spawn, finished);
capture.runAction(action);
},

6、下载图片到本地,动态生成a标签,模拟点击后移除

downloadImg() {
this.createSprite();
var img = this.initImage();
this.showSprite(img)
var dataURL = this._canvas.toDataURL("image/png")
var a = document.createElement("a")
a.href = dataURL;
a.download = "image";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
},

完整代码如下:

cc.Class({
extends: cc.Component, properties: {
_canvas: null,
targetNode: cc.Node
},
onLoad() {
this.init();
}, init() {
let texture = new cc.RenderTexture();
let gl = cc.game._renderContext;
texture.initWithSize(this.node.width, this.node.height, gl.STENCIL_INDEX8);
this.camera = this.node.addComponent(cc.Camera);
this.camera.targetTexture = texture;
this.texture = texture;
},
// create the img element
initImage(img) {
// return the type and dataUrl
var dataURL = this._canvas.toDataURL("image/png");
var img = document.createElement("img");
img.src = dataURL;
return img;
},
// create the canvas and context, filpY the image Data
createSprite() {
let width = this.texture.width;
let height = this.texture.height;
if (!this._canvas) {
this._canvas = document.createElement('canvas');
this._canvas.width = width;
this._canvas.height = height;
} else {
this.clearCanvas();
}
let ctx = this._canvas.getContext('2d');
this.camera.render();
let data = this.texture.readPixels();
// write the render data
let rowBytes = width * 4;
for (let row = 0; row < height; row++) {
let srow = height - 1 - row;
let imageData = ctx.createImageData(width, 1);
let start = srow * width * 4;
for (let i = 0; i < rowBytes; i++) {
imageData.data[i] = data[start + i];
} ctx.putImageData(imageData, 0, row);
}
return this._canvas;
},
getTargetArea() {
let targetPos = this.targetNode.convertToWorldSpaceAR(cc.v2(0, 0))
let y = cc.winSize.height - targetPos.y - this.targetNode.height / 2;
let x = cc.winSize.width - targetPos.x - this.targetNode.width / 2;
return {
x,
y
}
},
downloadImg() {
this.createSprite();
var img = this.initImage();
this.showSprite(img)
var dataURL = this._canvas.toDataURL("image/png")
var a = document.createElement("a")
a.href = dataURL;
a.download = "image";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
},
// show on the canvas
showSprite(img) {
let y = this.getTargetArea().y;
let x = this.getTargetArea().x;
let rect = new cc.Rect(x, y, 770, 800)
let texture = new cc.Texture2D();
texture.initWithElement(img); let spriteFrame = new cc.SpriteFrame();
spriteFrame.setTexture(texture);
spriteFrame.setRect(rect) let node = new cc.Node();
let sprite = node.addComponent(cc.Sprite);
sprite.spriteFrame = spriteFrame; node.zIndex = cc.macro.MAX_ZINDEX;
node.parent = cc.director.getScene();
// set position
let width = cc.winSize.width;
let height = cc.winSize.height;
node.x = width / 2;
node.y = height / 2;
node.on(cc.Node.EventType.TOUCH_START, () => {
node.parent = null;
node.destroy();
});
this.captureAction(node, width, height);
},
// sprite action
captureAction(capture, width, height) {
let scaleAction = cc.scaleTo(1, 0.3);
let targetPos = cc.v2(width - width / 6, height / 4);
let moveAction = cc.moveTo(1, targetPos);
let spawn = cc.spawn(scaleAction, moveAction); let finished = cc.callFunc(() => {
capture.destroy();
})
let action = cc.sequence(spawn, finished);
capture.runAction(action);
}, clearCanvas() {
let ctx = this._canvas.getContext('2d');
ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
}
});
网络释义
RenderTexture: 渲染纹理

cocos creator 小游戏区域截图功能实现的更多相关文章

  1. Cocos开发小游戏如何实现微信排行榜

    当游戏开发进入尾声,要引入微信数据的时候,需要了解和微信相关的接口了. 关系数据链 开放数据域 相关接口如下: wx.getFriendCloudStorage() 获取当前用户也玩该小游戏的好友的用 ...

  2. Cocos Creator采坑:原来使用Cocos Creator做游戏,是有服务器!!!

    我傻傻的以为,我们没有服务器. 今天上传测试代码,测试才发现! 原来我们真的是有服务器的!只不过是一个本地的服务器~!需要服务器打开,然后,扫码才能访问!! 为了证明我们是有服务器的,我做了一下测试 ...

  3. Cocos Creator经典游戏制作之:信使(The Messenger)

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  4. cocos 微信小游戏切后台卡住

    1.cocos 安装目录下搜索以下代码并注掉opts["preserveDrawingBuffer"] = true;”2.CocosCreator\resources\engin ...

  5. 新编辑器Cocos Creator发布:对不起我来晚了!

    1月19日,由Cocos创始人王哲亲手撰写的一篇Cocos Creator新品发布稿件在朋友圈被行业人士疯狂转载,短短数小时阅读量突破五位数.Cocos Creator被誉为“注定将揭开Cocos开发 ...

  6. cocos creator主程入门教程(一)—— 初识creator

    五邑隐侠,本名关健昌,10年游戏生涯,现隐居五邑.本系列文章以TypeScript为介绍语言. 我们在cocos creator新建一个Hello TypeScript项目,都会有一个assets/S ...

  7. cocos creator 入门理解点

    简单解释, [来源:官方文档] Cocos是触控科技推出的游戏开发一站式解决方案,包含了从新建立项.游戏制作.到打包上线的全套流程.开发者可以通过cocos快速生成代码.编辑资源和动画,最终输出适合于 ...

  8. 一个js小游戏----总结

    花了大概一天左右的功夫实现了一个js小游戏的基本功能,类似于“雷电”那样的小游戏,实现了随即怪物发生器,碰撞检测,运动等等都实现了,下一个功能是子弹轨迹,还有其他一些扩展功能,没有用库,也没有用web ...

  9. h5小球走迷宫小游戏源码

    无意中找到的一个挺有意思的小游戏,关键是用h5写的,下面就分享给大家源码 还是先来看小游戏的截图 可以用键盘的三个键去控制它,然后通关 下面是源代码 <!doctype html> < ...

随机推荐

  1. QT中的各种对话框

    大家可以参见QT中各种MessageBox的使用的这篇文章 界面效果图如下,大家可以用代码自己操作 diglog.h #ifndef DIALOG_H #define DIALOG_H #includ ...

  2. [铁人赛] ASP.NET Core 2 系列- 从头开始

    来势汹汹的.NET Core似乎要取代.NET Framework,ASP.NET也随之发布.NET Core版本.虽说名称沿用ASP.NET,但相较于ASP.NET确有许多架构上的差异,可说是除了名 ...

  3. Mac OS下terminal的快捷键

    时隔2年又开始使用Mac OS系统,之前的很多快捷键和常用的命令都忘记了,使用起来确实不方便,效率也低,特别是terminal下,所以对于terminal又找了一下并整理如下,希望对后来的同学也有用: ...

  4. DataVeryLite入门教程(二) Entity篇

    DataVeryLite 是基于.net 4.0的数据库持久化ORM框架. 目前支持的数据库有Sqlserver,Mysql,Oracle,Db2,PostgreSql,Sqlite和Access. ...

  5. linux dll hell--链接库real name, soname, link name

    DLL hell 是指 Windows 系统上动态库的新版本覆盖旧版本,且新版本不能兼容旧版本的问题. 例如:装新软件,但原有的软件运行不起来了.   Linux 系统下也同样面临着和 Windows ...

  6. SpringCloud系列——TX-LCN分布式事务管理

    前言 SpringCloud分布式架构给我们带来开发上的便利,同时增加了我们对事务管理的难度,微服务的遍地开花,本地事务已经无法满足分布式的要求,由此分布式事务问题诞生. 分布式事务被称为世界性的难题 ...

  7. Hadoop 学习之路(四)—— Hadoop单机伪集群环境搭建

    一.前置条件 Hadoop的运行依赖JDK,需要预先安装,安装步骤见: Linux下JDK的安装 二.配置免密登录 Hadoop组件之间需要基于SSH进行通讯. 2.1 配置映射 配置ip地址和主机名 ...

  8. MySQL下的DB Link

    前言: 在实际工作中,我们可能会遇到需要操作其他数据库实例的部分表,但又不想系统连接多库.此时我们就需要用到数据表映射.如同Oracle中的DBlink一般,使用过Oracle DBlink数据库链接 ...

  9. Java虚拟机详解(二)------运行时内存结构

    首先通过一张图了解 Java程序的执行流程: 我们编写好的Java源代码程序,通过Java编译器javac编译成Java虚拟机识别的class文件(字节码文件),然后由 JVM 中的类加载器加载编译生 ...

  10. mongoshell 执行JavaScript文件获取数据库实例基本信息

    由于MongoDB没有关系型数据中强大的数据字典.因此,如果需要汇总统计一些内部信息,包括数据量,基本元信息,集群架构,状态信息.则需要自己写脚本统计.为日后工作方便,本人在此将一些统计信息通过Jav ...