本节会详细介绍下,如何绘制面板的背景。
概述
常用的技术称为图块复制(blitting),即从离屏缓冲区中将内容发生变化的那部分背景图像复制到屏幕上,还有其它两种方法是将所有内容擦除并重新绘制&仅重绘内容发生变化的那部分区域。一般是用clip()方法来实现的.如果背景比较简单采用将所有内容擦除再重新绘制可能性能更好。
代码示例
基本上下文设置
/*
【1】、用这些技术不用担心闪屏的问题,因为浏览器在实现时都采用了双缓冲技术。即把修改后的图像放在离屏文件中,然后一次性复制到显示区域内。**不需要个人实现**
*/
//整个绘制的技术
context.save();
context.clearRect(0, 0, canvas.width, canvas.height);
drawBackground();
context.restore();
//利用剪辑区域技术来恢复上一帧动画所占背景图像的执行步骤,这种技术只能操作简单的图像,如果canvas上对象比较多也会比较吃力,最好的方法还是blitting。
context.save();//保存屏幕canvas的状态
context.beginPath();//开始一段新的路径
context.arc();//设置路径
context.clip();//设置剪辑区
eraseBackground();//擦除上一帧物体的图像
drawBackground();//绘制整个背景,因为设置了剪辑区所以只会绘制那一部分
context.restore();//恢复canvas状态
/*blitting技术,将整个背景一次性绘制到离屏canvas中,稍后从离屏canvas中只将修复动画背景所需的那一块图像复制到屏幕上,它比其它技术要快,缺点是离屏文件占用了部分内存*/
context.save();
context.beginPath();
context.arc();
context.clip();
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(offscreenCanvas, ......);//从离屏文件中复制那一小布内容到显示区域上
context.restore();
背景滚动技术
背景滚动技术,当有多个物体时,场景会有远近,所以背景滚动时,后面的要移动的慢,前面的要快些,这样造成了视觉我看着
//....................背景滚动技术......................................
var lastTime = 0,
fps = 0,
skyOffset = 0,
SKY_VELOCITY = 300; // 30 pixels/second,预先设定的速度,这个值设定好是有原因的,因为像汽车这样的游戏,速度多少是要根据实际情况换算出来的
function draw() {
context.save();
skyOffset = skyOffset < canvas.width ?
skyOffset + SKY_VELOCITY/fps : 0;
context.save();
context.translate(-skyOffset, 0);
context.drawImage(sky, 0, 0);
context.drawImage(sky, sky.width-2, 0);//绘制两次是为了做个简单的循环
context.restore();
}
//计算出帧数,这是由requestAnimationFrame()方法间隔来计算的
function calculateFps(now) {
var fps = 1000 / (now - lastTime);
lastTime = now;
return fps;
}
/*这种技术主要是SKY_VELOCITY的不同值来实现的,需要注意的是为了循环的首尾相接,所以每个图像都要复制两份,并注意save()和restore()的使用*/
var TREE_VELOCITY = 20,
FAST_TREE_VELOCITY = 40,
SKY_VELOCITY = 8,
GRASS_VELOCITY = 75;
function draw() {
context.save();
//计算不同的速度
skyOffset = skyOffset < canvas.width ?
skyOffset + SKY_VELOCITY/fps : 0;
grassOffset = grassOffset < canvas.width ?
grassOffset + GRASS_VELOCITY/fps : 0;
treeOffset = treeOffset < canvas.width ?
treeOffset + TREE_VELOCITY/fps : 0;
nearTreeOffset = nearTreeOffset < canvas.width ?
nearTreeOffset + FAST_TREE_VELOCITY/fps : 0;
//每个都要复制两次*************
context.save();
context.translate(-skyOffset, 0);
context.drawImage(sky, 0, 0);
context.drawImage(sky, sky.width-2, 0);
context.restore();
context.save();
context.translate(-treeOffset, 0);
context.drawImage(tree, 100, 240);
context.drawImage(tree, 1100, 240);
context.drawImage(tree, 400, 240);
context.drawImage(tree, 1400, 240);
context.drawImage(tree, 700, 240);
context.drawImage(tree, 1700, 240);
context.restore();
context.save();
context.translate(-nearTreeOffset, 0);
context.drawImage(nearTree, 250, 220);
context.drawImage(nearTree, 1250, 220);
context.drawImage(nearTree, 800, 220);
context.drawImage(nearTree, 1800, 220);
context.restore();
context.save();
context.translate(-grassOffset, 0);
context.drawImage(grass, 0, canvas.height-grass.height);
context.drawImage(grass, grass.width-5, canvas.height-grass.height);
context.drawImage(grass2, 0, canvas.height-grass2.height);
context.drawImage(grass2, grass2.width,canvas.height-grass2.height);
context.restore();
}
//在这里插入HTML代码片断