目前市面上H5游戏的图片资源,基本都是采用SpriteSheet打包成图集来使用的。这样可以减少网络加载的次数,从而提升性能。另外的原因就是随着webgl的普及,把多张图片打包成一张纹理,减少纹理的频繁上传,这样也可以提升性能。本文主要是讨论使用Canvas实现的2D序列帧动画的SpriteSheet的解析和动画播放。
{
"res": {
"1_4_1": {
"x": 0,
"y": 0,
"w": 109,
"h": 149
},
"1_4_3": {
"x": 217,
"y": 0,
"w": 102,
"h": 148
},
"1_4_2": {
"x": 320,
"y": 0,
"w": 99,
"h": 150
},
"1_4_0": {
"x": 110,
"y": 0,
"w": 106,
"h": 146
}
},
"mc": {
"caiyi_idle": {
"labels": [{
"end": 4,
"frame": 1,
"name": "1_4"
}],
"frameRate": 5,
"frames": [{
"duration": 1,
"y": -148,
"res": "1_4_0",
"x": -85
},
{
"duration": 1,
"y": -150,
"res": "1_4_1",
"x": -80
},
{
"duration": 1,
"y": -150,
"res": "1_4_2",
"x": -78
},
{
"duration": 1,
"y": -149,
"res": "1_4_3",
"x": -81
}],
"events": []
}
}
}
4.源码例子下载
6.开发工具:IntelliJ IDEA
//获取canvas对象
var canvas = document.getElementById("canvas2D");
//2d渲染对象
context = canvas.getContext("2d");
xmlRequest = new XMLHttpRequest();
xmlRequest.open("GET", "caiyi_idle.json", true);
xmlRequest.send(null);
加载到游戏中,转成json对象,里面有对应的数据结构。这个很重要,每一帧显示什么样的图片就靠这个数据了。
var imageLoad = new Image();
imageLoad.src = "caiyi_idle.png";
//启动动画
setTimeout(tick, 1000 / frameRate);
drawImage(image, x, y)
drawImage(image, x, y, width, height)
drawImage(image, sourceX, sourceY, sourceWidth, sourceHeight,
destX, destY, destWidth, destHeight)
参数
image:所要绘制的图像。这必须是表示 <img> 标记或者屏幕外图像的 Image 对象,或者是 Canvas 元素。
x, y:要绘制的图像的左上角的位置。
width, height:图像所应该绘制的尺寸。指定这些参数使得图像可以缩放。
sourceX, sourceY :图像将要被绘制的区域的左上角。这些整数参数用图像像素来度量。
sourceWidth, sourceHeight:图像所要绘制区域的大小,用图像像素表示。
destX, destY:所要绘制的图像区域的左上角的画布坐标。
destWidth, destHeight:图像区域所要绘制的画布大小。
实现关键代码:
//进行绘图,这里是渲染大的部分图像
context.drawImage(image,rect.x,rect.y,rect.w,rect.h,240 + frame.x,200 + frame.y,rect.w,rect.h);
代码中有比较详细的注视。
html代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body onload="main()">
<canvas id="canvas2D" width="800" height="600">
Please use!
canvas>
<script src="MainTest.js">script>
body>
html>
js代码
/**
* 程序入口
*/
function main()
{
//获取canvas对象
var canvas = document.getElementById("canvas2D");
console.log("canvas:" + canvas);
//2d渲染对象
context = canvas.getContext("2d");
console.log("context:" + context);
//XMLHttpRequest加载json配置文件
xmlRequest = new XMLHttpRequest();
xmlRequest.open("GET", "caiyi_idle.json", true);
xmlRequest.onreadystatechange = onreadystatechange;
xmlRequest.send(null);
}
//xmlRequestxml的状态改变
function onreadystatechange()
{
if (xmlRequest.readyState==4)
{
//加载成功,生成json对象
idleConfig = JSON.parse(xmlRequest.responseText);
//加载图片
var imageLoad = new Image();
imageLoad.onload = function (event)
{
//加载完成,初始化json配置图像
image = event.target;
initImage();
}
imageLoad.src = "caiyi_idle.png";
}
}
function initImage()
{
console.log("准备处理SpriteSheet.......");
/** 当前帧 **/
currentFrame = 0;
movieData = idleConfig.mc["caiyi_idle"];
/** 帧频 **/
frameRate = movieData.frameRate;
/** 提取出的动画全部帧数 **/
frames = movieData.frames;
/** 最大帧 **/
maxFrame = frames.length;
//启动动画
setTimeout(tick, 1000 / frameRate);
}
/**
* 动画心跳函数,按照一定的频率定时执行
*/
function tick()
{
//获取帧数据和每帧的位置以及宽高数据
var frame = frames[currentFrame];
var rect = idleConfig.res[frame.res];
//先清掉原来的画布
context.clearRect(0,0,480,240);
//画个背景,设置背景颜色
context.fillStyle = "#003366";
//填充个480 * 240的矩形
context.fillRect(0,0,480,240);
//进行绘图,这里是渲染大图的部分图像,具体看api参数。
context.drawImage(image,rect.x,rect.y,rect.w,rect.h,240 + frame.x,200 + frame.y,rect.w,rect.h);
currentFrame++;
//如果等于最打帧,则重新从0开始
if(currentFrame >= maxFrame)
currentFrame = 0;
//启动动画,循环播放
setTimeout(tick.bind(this), 1000 / frameRate);
}