HTML5 Canvas 视差滚动背景的OOP实现

在最开始的博文中,我用简单的方式实现了一个视差滚动动画的示例。在本文中将对它进行OOP重写,以便能使视差滚动背景动画加入到我的游戏框架之中。

重用的代码段:

HTML:

Your browser does not support the canvas element!

JavaScript:

Array.prototype.remove = function(obj) { for (i in this) { if (this[i] === obj) { this.splice(i, 1); } } } function BasicObject(x, y, order) { this.x = x; this.y = y; this.order = isNaN(order) ? 0 : order; this.addTo = function(list) { list.push(this); list.sort(function(a, b) {return a.order - b.order;}); } this.removeFrom = function(list) { list.remove(this); } } window.onload = function() { new Engin().run(); }下面是新添加的对象:

静态背景对象,继承自基础对象类,用于绘制静态的背景图,可以设置为重复绘制(将repeat置为1):

function Background(image, x, y, order, repeat) { BasicObject.call(this, x, y, order); this.image = image; this.repeat = (repeat == 1) ? true : false; this.draw = function(canvas) { var context = canvas.getContext("2d"); if (this.repeat) { context.save(); var pattern = context.createPattern(this.image, 'repeat'); context.fillStyle= pattern; context.fillRect(this.x, this.y, canvas.width, canvas.height); } else { context.drawImage(this.image, this.x, this.y); } } } Background.prototype = new BasicObject();X方向的滚动对象,继承自静态背景对象,需要传入的参数包括图像、滚动的速度、图像在画布中左右角的X / Y坐标、绘制的顺序。

function XScrollBackground(image, speed, x, y, order) { Background.call(this, image, x, y, order); this.speed = speed; this.sx = 0; this.sy = 0; this.update = function() { this.sx = (this.sx + this.speed) % this.image.width; } this.draw = function(canvas) { var context = canvas.getContext("2d"); if (this.sx + canvas.width > this.image.width) { var d0 = this.image.width - this.sx; var d1 = canvas.width - d0; context.drawImage(this.image, this.sx, this.sy, d0, this.image.height, this.x, this.y, d0, this.image.height); context.drawImage(this.image, 0, this.sy, d1, this.image.height, this.x + d0, this.y, d1, this.image.height); } else { context.drawImage(this.image, this.sx, this.sy, canvas.width, this.image.height, this.x, this.y, canvas.width, this.image.height); } } } XScrollBackground.prototype = new Background();由于update方法的参数由context改为了canvas,所以引擎类也随之改变

function Engin() { var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); var buffer = document.createElement("canvas"); buffer.width = canvas.width; buffer.height = canvas.height; var bufferCtx = buffer.getContext("2d"); var objs = new Array(); const FPS = 60; this.manage = function() { bufferCtx.clearRect(0, 0, buffer.width, buffer.height); context.clearRect(0, 0, canvas.width, canvas.height); for (x in objs) { if (objs[x].update) { objs[x].update(objs); } } for (x in objs) { if (objs[x].draw) { objs[x].draw(buffer); } } context.drawImage(buffer, 0, 0); } this.run = function() { var bg0 = new Image(); var bg1 = new Image(); var bg2 = new Image(); bg0.src = "bg0.png"; bg1.src = "bg1.png"; bg2.src = "bg2.png"; var speed = 2.5; var xsb0 = new XScrollBackground(bg0, speed * 0.5, 0, 0, 0); xsb0.addTo(objs); var xsb1 = new XScrollBackground(bg1, speed * 0.75, 0, 100, 1); xsb1.addTo(objs); var xsb2 = new XScrollBackground(bg2, speed * 1, 0, 100, 2); xsb2.addTo(objs); setInterval(this.manage, 1000 / FPS); } }
需要特别注意的是Context对象的drawImage方法。该方法的原型之一void drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);中,如果sx, sy, sw, sh超过了图像本身的范围,即所取的图像左上角点不在图像之中,或者所取的图像宽度或者高度超出了图像真实的宽或高,就会报出Uncaught Error: INDEX_SIZE_ERR: DOM Exception 1错误。对drawImage方法想要更多了解的,请查看《HTML5 Canvas初步》·图片

你可能感兴趣的:(HTML5 Canvas 视差滚动背景的OOP实现)