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

本文详细介绍了如何使用面向对象编程(OOP)重写视差滚动动画,以便将其集成到游戏框架中。通过提供HTML、JavaScript代码示例,以及新增的静态背景对象和X方向滚动对象,展示了如何实现动态背景效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在最开始的博文中,我用简单的方式实现了一个视差滚动动画的示例。在本文中将对它进行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初步》·图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值