cocos creator 小游戏区域截图功能实现
截图是游戏中非常常见的一个功能,在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);
}
});
cocos creator 小游戏区域截图功能实现的更多相关文章
- Cocos开发小游戏如何实现微信排行榜
当游戏开发进入尾声,要引入微信数据的时候,需要了解和微信相关的接口了. 关系数据链 开放数据域 相关接口如下: wx.getFriendCloudStorage() 获取当前用户也玩该小游戏的好友的用 ...
- Cocos Creator采坑:原来使用Cocos Creator做游戏,是有服务器!!!
我傻傻的以为,我们没有服务器. 今天上传测试代码,测试才发现! 原来我们真的是有服务器的!只不过是一个本地的服务器~!需要服务器打开,然后,扫码才能访问!! 为了证明我们是有服务器的,我做了一下测试 ...
- Cocos Creator经典游戏制作之:信使(The Messenger)
版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...
- cocos 微信小游戏切后台卡住
1.cocos 安装目录下搜索以下代码并注掉opts["preserveDrawingBuffer"] = true;”2.CocosCreator\resources\engin ...
- 新编辑器Cocos Creator发布:对不起我来晚了!
1月19日,由Cocos创始人王哲亲手撰写的一篇Cocos Creator新品发布稿件在朋友圈被行业人士疯狂转载,短短数小时阅读量突破五位数.Cocos Creator被誉为“注定将揭开Cocos开发 ...
- cocos creator主程入门教程(一)—— 初识creator
五邑隐侠,本名关健昌,10年游戏生涯,现隐居五邑.本系列文章以TypeScript为介绍语言. 我们在cocos creator新建一个Hello TypeScript项目,都会有一个assets/S ...
- cocos creator 入门理解点
简单解释, [来源:官方文档] Cocos是触控科技推出的游戏开发一站式解决方案,包含了从新建立项.游戏制作.到打包上线的全套流程.开发者可以通过cocos快速生成代码.编辑资源和动画,最终输出适合于 ...
- 一个js小游戏----总结
花了大概一天左右的功夫实现了一个js小游戏的基本功能,类似于“雷电”那样的小游戏,实现了随即怪物发生器,碰撞检测,运动等等都实现了,下一个功能是子弹轨迹,还有其他一些扩展功能,没有用库,也没有用web ...
- h5小球走迷宫小游戏源码
无意中找到的一个挺有意思的小游戏,关键是用h5写的,下面就分享给大家源码 还是先来看小游戏的截图 可以用键盘的三个键去控制它,然后通关 下面是源代码 <!doctype html> < ...
随机推荐
- Linux命令行和shell编程
Shell Shell是一个程序,用户输入的命令通过shell来传达给内核或其它程序.用户在linux打开一个终端,终端就会自动调用用户的shell. Linux上的Shell有很多种,用的最多是sh ...
- java-mysql(3) 读写image
在mysql里面用来存储图片有一个特殊的数据对象叫做 Blob(Binary Large Object). 数据库里面插入一张图片: 第一步:需要为图片创建一个文件对象 File img = new ...
- Spring Boot:整合JdbcTemplate
综合概述 Spring对数据库的操作在jdbc上面做了更深层次的封装,而JdbcTemplate便是Spring提供的一个操作数据库的便捷工具.我们可以借助JdbcTemplate来执行所有数据库操作 ...
- Hive的一些学习内容
Hive相关 什么是metastore? metadata是元数据,包含数据库.表.字段.分区等信息.作用:客户端连接MetaStore服务,metastore再去连接MySQL数据库存储元数据,有了 ...
- Hive 学习之路(七)—— Hive 常用DML操作
一.加载文件数据到表 1.1 语法 LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (p ...
- 如何两个月刷400道leetcode
前言随着互联网寒潮的到来, 越来越多的互联网公司提高了面试的难度,其中之一就是加大了面试当中手撕算法题的比例.这里说的算法题不是深度学习,机器学习这类的算法,而是排序,广度优先,动态规划这类既考核数据 ...
- redis 安装和单机多节点集群
环境: centOs系统 一.安装redis: 1.下载安装(先装c编译器yum -y install gcc) $ wget http://download.redis.io/releases/re ...
- 02-三种Bean装配机制(一)
Spring要创建哪些bean并且如何将其装配在一起,现有的,主要是三种装配机制: 自动化装配 通过java代码装配 通过XML装配 这三种装配机制可以互相搭配使用,即是可以共存的.接下来就分别介绍啦
- myecliese加大内存
加大内存代码 : -Xms512m -Xmx1024m -XX:PermSize=256M -XX:MaxPermSize=1024m
- iOS 国际化 (国际化文字内容不改变,app名字国际化,一键切换语言)
首先我们要分三个步骤讲解怎么一步步实现app名字国际化.内容国际化.一键切换国际化的: 一.app设置内容或者可以说是app名字或者可以说Info.Plist中的东西国际化 app名字国际化 1. ...