在最开始的博文中,我用简单的方式实现了一个视差滚动动画的示例。在本文中将对它进行OOP重写,以便能使视差滚动背景动画加入到我的游戏框架之中。
重用的代码段:
HTML:
<canvas id="canvas" width="600" height="400">
<p>Your browser does not support the canvas element!</p>
</canvas>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初步》·图片
本文详细介绍了如何使用面向对象编程(OOP)重写视差滚动动画,以便将其集成到游戏框架中。通过提供HTML、JavaScript代码示例,以及新增的静态背景对象和X方向滚动对象,展示了如何实现动态背景效果。

被折叠的 条评论
为什么被折叠?



