HTML5-Canvas: Viết game Mario – Part 2

mario_iconTiếp theo phần 1, trong phần này ta sẽ tìm hiểu cách thêm vào hai đối tượng đặc trưng của game Mario là như nấm và vàng.


Xem Demo.

Html5-Canvas-Mario part2

Tạo lớp Mushroom

Bạn có thể thấy là cách hoạt động của các cây nấm (thức ăn của Mario) không khác gì so với các đối tượng Monster. Vì vậy việc tạo lớp này cũng tương tự:

function Mushroom(map,left,top){
	// call the super-constructor
	Character.call(this,map,{
		left: left,
		top: top,
		speed: 1,
		isAutoMoving: true
	});
}
Mushroom.prototype = new Character();
Mushroom.prototype.draw = function(context){

	context.save();
	context.beginPath();
	var left = this.left-this.map.offsetX;
	var top = this.top-this.map.offsetY;
	var right = left+this.width;
	var bottom = top+this.height;
	var hw = this.width/2;
	var cx = left+hw;

	context.fillStyle = "red";
	context.arc(cx,top+hw,hw-2,0,Math.PI*2,true);
	context.fill();
	context.restore();
}

Thay đổi lớp Map

Dữ liệu của lớp Map cần được thay đổi để bổ sung các loại đối tượng mới: vàng (gold), gạch chứa nấm và một loại gạch không thể phá hủy.

var BRICK = 2;
var HARD_BRICK= 3;
var MUSHROOM_BRICK = 4;
// …
var GOLD = 7;

Để vẽ được hình ellipse (gold), tôi bổ sung một phương thức drawEllipse vào lớp CanvasRenderIngContext2D:

CanvasRenderingContext2D.prototype.drawEllipse = function(centerX, centerY, width, height) {

  this.beginPath();

  this.moveTo(centerX, centerY - height/2);

  this.bezierCurveTo(
    centerX + width/2, centerY - height/2,
    centerX + width/2, centerY + height/2,
    centerX, centerY + height/2);

  this.bezierCurveTo(
    centerX - width/2, centerY + height/2,
    centerX - width/2, centerY - height/2,
    centerX, centerY - height/2);

	this.closePath();
  this.fill();
}

Phương thức quan trọng của lớp này là kiểm tra va chạm, dựa vào thuộc tính canEat của lớp Character, ta sẽ xác định được một nhân vật có thể “ăn” được một đối tượng nào đó hay không (như nấm, vàng).
– Trong trường hợp ô bị va chạm là vàng, ta cộng thêm 100 điểm và trả về void, có nghĩa là coi như không va chạm.
– Nếu đó là gạch chứa nấm, thêm một đối tượng Mushroom vào tại vị trí phía trên viên gạch.

// map
this.colllide = function(x,y,canDestroy,canEat){
	var b = this.contain(x,y);

	if(b)
	{
		if(b.type==GOLD)
		{
			if(canEat)
			{
				this.scores += 100;
				clearCell(b.left,b.top,b.col,b.row);
			}
			return;
		}

		if(canDestroy && b.type!=HARD_BRICK)
		{
			if(b.type==BRICK)
			{
				clearCell(b.left,b.top,b.col,b.row);
			}
			else if(b.type==MUSHROOM_BRICK) // add new mushroom
			{
				data[b.col+b.row*COLS] = HARD_BRICK;
				context.fillStyle = "Brown";
				context.fillRect(b.left,b.top,CELL_SIZE,CELL_SIZE);

				this.mushrooms.push(new Mushroom(this,b.left,b.top-CELL_SIZE));
			}

		}
		return b;
	}
	return false;
};

Phương thức update() của lớp này tương như phần trước ngoại trừ thêm phần cập nhật các Mushroom vào.

var i=0;
var length = this.mushrooms.length;
while(i<length){
	if(this.mushrooms[i].isDead)
	{
		this.mushrooms.splice(i,1);
		length--;
	}else
	{
		this.mushrooms[i].update();
		i++;
	}
}

Làm nhân vật lớn lên hoặc nhỏ lại

Đối với lớp Player, tôi tạo thêm một thuộc tính isChild để xác định kích thước của nhân vật này. Sau đó tạo một hàm để thay đổi các thuộc tính cần thiết khi Player chạm phải nấm hay kẻ địch. Trong trường hợp Player đang là người lớn và bị va chạm với kẻ địch, ta sẽ cho Player “bất tử” trong vòng 1 giây để họ có thời gian né sang vị trí khác:

Player.prototype.grow = function(){

	if(this.isChild) // grow up
	{
		this.height *= 1.5;
		this.width *= 1.5;
	}else	// grow down
	{
		this.height /= 1.5;
		this.width /= 1.5;
		this.immuneCount = FPS; // make character immune for 1 seconds
	}
	this.top = this.bottom - this.height;
	this.isChild = !this.isChild;
}

Phương thức update() mới:

Player.prototype.collide = function(monsters,mushrooms){
	for(m in monsters)
	{
		var mon = monsters[m];

		if(!(this.left > mon.right ||
			this.right < mon.left ||
			this.top > mon.bottom ||
			this.bottom < mon.top))
			{
				if(this.bottom<mon.bottom&& this.speedY>0)
				{
					mon.die();
				}
				else
				{
					if(this.isChild)
					{
						if(this.immuneCount==0)
						{
							this.die();
							break;
						}
					}
					else
						this.grow(); // grow down
				}
			}

	}

	for(var i=0;i<mushrooms.length;i++)
	{
		var m = mushrooms[i];

		if(!(this.left > m.right ||
			this.right < m.left ||
			this.top > m.bottom ||
			this.bottom < m.top))
			{
				if(this.isChild)
					this.grow();
				else
					this.map.scores+=1000;
				m.die();
			}

	}
}

Trong game này, tôi cũng thay đổi một chút để cho phép Monster có thể lớn lên khi ăn được nấm.

YinYangIt’s Blog

4 thoughts on “HTML5-Canvas: Viết game Mario – Part 2

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