Html5-Canvas: Viết game Tower Defense – part 3

Trong phần này ta sẽ thêm khả năng bắn đạn của tower cũng như HP của các enemy. Như thường lệ tôi sẽ cố gắng viết các comment trong code để người đọc có thể hiểu ngay. Phần bài viết này chỉ có nhiệm vụ dẫn dắt bạn vào những phần chính.
Nếu đây là phần đầu tiên bạn đọc, bạn có thể quay lại đọc các phần 1, 2.


Xem Demo.

Html5-TowerDefense-part3

HP của Enemy

Ta sẽ vẽ một thanh màu đỏ phía trên mỗi enemy để người chơi ước lượng được % lượng HP còn lại của chúng. Khi khởi tạo Enemy, ta thêm thuộc tính mới cho lớp này:

function Enemy(roadX,roadY){
	var maxhp = 1000;
	this.hp = maxhp;
	// ...c
}

Vẽ thanh HP:

this.draw = function(context){
	// ...
	context.fillStyle = "red";
	context.fillRect(this.left,this.top - 5, UNIT_SIZE * this.hp / maxhp, 3);
};

Và bổ sung phương thức để kiểm tra xem enemy có dính đạn hay không (mỗi viên đạn được coi là một điểm):

this.contain = function(x, y){
	return this.left <= x && this.top <= y &&
			this.right >= x && this.bottom >=y;

};

Bullet – Đạn

Trong lớp này, ta sẽ xác định hướng di chuyển của mỗi viên đạn từ góc xoay của tower tạo ra nó. Trong đó, ta cũng cần một phương thức để kiểm tra va chạm của đạn với enemy. Khi va chạm xảy ra, ta sẽ trừ HP của enemy dựa vào chỉ số damage của tower:

this.collide = function(damage, enemies){
	for(var i = 0; i < enemies.length; i++)
	{
		var e = enemies[i];

		if(!e.isDisposed && e.contain(this.cx, this.cy))
		{
			e.hp -= damage;
			if(e.hp <= 0)
			{
				e.hp = 0;
				e.isDisposed = true;
			}
			this.isDisposed = true;
			return;

		}
	}
};

Ngoài ra cần đảm bảo rằng tầm bay của đạn không vượt quá phạm vi bắn của tower. Vì vậy trong phương thức update(), ta sẽ lưu lại khoảng cách mà đã bay. Và khi đã vượt qua giới hạn, ta cần hủy nó:

this.update = function(){

	this.cx += speedX;
	this.cy += speedY;
	distance += speed;

	if(distance >= range)
		this.isDisposed = true;
};

Tower

Đây là lớp thay đổi nhiều nhất vì phải thêm các thuộc tính, biến mới:

this.damage = 100;
var bullets = [];
var lastFired = 0;
var fireDelay = 400; // fire rate
var target;

Trong đó, biến target giúp lưu trữ đối tượng enemy mà tower đang nhắm vào. Như vậy ta không cần lặp qua để tìm enemy gần nhất mỗi lần update. Chỉ cần kiểm tra khoảng cách giữa tower vừa target, nếu nó nằm ngoài tầm bắn thì ta mới tìm kiếm một enemy khác:

this.update = function(enemies){

	var targetAngle;

	if(target)
	{
		if(target.isDisposed)
			target = null;
		else {
			// check if the target is within the shooting range
			var dx = target.cx - this.cx;
			var dy = target.cy - this.cy;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if(distance <= this.shootingRange)
			{
				targetAngle = Math.atan2(dy, dx);
				if(Math.abs(this.angle - targetAngle) < ANGLE_EPSILON)
				{

					// fire the enemy
					var newtick = (new Date()).getTime();
					if(newtick - lastFired >= fireDelay)
					{

						this.fire();
						lastFired = newtick;

					}
				}
			}else
				// the target is out of shooting range,
				// we need to find a new target
				target = null;
		}
	}

	if(!target){
		// find the nearest enemy within range
		for(var x in enemies)
		{
			var e = enemies[x];
			var dx = e.cx - this.cx;
			var dy = e.cy - this.cy;
			var distance = Math.sqrt(dx * dx + dy * dy);

			if(distance <= this.shootingRange)
			{
				targetAngle = Math.atan2(dy, dx);
				target	= e;
				break;
			}
		}
	}
	// ...
};

YinYangIt’s Blog

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s