Html5-Canvas: Phóng to/thu nhỏ game bằng nút cuộn chuột

zoom_len_view_iconBài viết này được thực hiện theo yêu cầu của bạn xtranfor55 trong bài viết Cuộn ảnh nền và bản đồ (Map Scrolling). Tôi sẽ hướng dẫn cách làm điều này bằng cách 2 cách: sử dụng Canvas API và xử lý thủ công trong code.

Để thay đổi kích thước nội dung trong canvas, cách tốt nhất là sử dụng phương thức context.scale(double x, double y) để thiết lập một tỉ lệ co giãn khi vẽ bằng context. Phương thức này giúp hình ảnh trong canvas vẫn giữ được độ nét như với các ảnh vector (không như việc bạn thay đổi kích thước của canvas bằng css hoặc chức năng zoom của trình duyệt).
Bởi vì cách trên quá đơn giản nên tôi sẽ dừng lại tại đây và tập trung vào phần xử lý thủ công. Qua đó, bạn có thể áp dụng cho những nền tảng game khác không hỗ trợ tranformation.

Bạn có thể áp dụng cách làm trong ví dụ này cho những ứng dụng tương tự, chủ yếu là thay đổi kích thước của một đơn vị (CELL_SIZE), của đối tượng và thay đổi tọa độ.

Xem Demo

Sự kiện Mouse Wheel trong javascript

Hoạt động của nút cuộn chuột được xác định bởi một giá trị delta lấy được từ tham số event của sự kiện mousewheel (hoặc DOMMouseScroll trên Firefox). Giá trị này cho biết chiều và độ lớn vòng quay của bánh xe. Bạn có thể đọc một bài hướng dẫn cụ thể tại Mouse wheel programming in JavaScript.

Trong ví dụ này tôi chỉ quan tâm đến chiều quay của bánh xe: với giá trị âm, tôi giảm kích thước nội dung bên trong canvas đi 1/2 và với giá trị dương tôi tăng nó lên 2 lần.

function canvas_mousewheel(e){
	var delta = 0;
	if (!e) /* For IE. */
		   e = window.e;
	if (e.wheelDelta) { /* IE/Opera. */
			delta = e.wheelDelta/120;
	} else if (e.detail) { /** Mozilla case. */
		delta = -e.detail/3;
	}
	if (delta)
	{
		_map.changeZoom(delta);
		_ball.setZoom(_map.zoom);
		draw();
	}

	if (e.preventDefault)
			e.preventDefault();
}

Thay đổi kích thước bản đồ

Trong các ví dụ sử dụng bản đồ, tôi định nghĩa một hằng CELL_SIZE quy định kích thước của một ô theo pixel. Như vậy để thay đổi kích thước bản đồ không có gì phức tạp.

Trong ví dụ này tôi tạo một thuộc tính zoom=1 xác định tỉ lệ kích thước ban đầu. Giá trị tối thiểu nó có thể nhận được là 0.5 và lớn nhất là 4:

Map.prototype = {
	changeZoom : function(zoom){

		if(zoom == 0 || (zoom<0 && this.zoom<=0.5) || (zoom>0 && this.zoom>=4))
			return;

		this.zoom *= zoom < 0 ? 0.5 : 2;

		this.reset();
	},
	reset : function()
	{
		this.cellSize = CELL_SIZE*this.zoom;

		this.width = MAP_WIDTH*this.cellSize ;
		this.height = MAP_HEIGHT*this.cellSize ;

	}
	// ...
}

Phương thức reset() trên thực hiện cập nhật ba thuộc tính quan trọng của bản đồ khi thay đổi tỉ lệ kích thước.

Vẽ từng vùng bản đồ

Với dữ liệu của bản đồ được lưu trữ trong một mảng hai chiều. Ta cần xác định được vị trí, số lượng dòng và cột cần được hiển thị và chỉ vẽ vùng này lên canvas.

// draw method
var col = Math.floor(this.offsetX/this.cellSize);
var row = Math.floor(this.offsetY/this.cellSize);
ctx.fillStyle = "black";

for(var i=col;i<col+Math.floor(this.viewWidth/this.cellSize)+1;i++)
{
	if(this.data[i])
	for(var j=row;j<row+Math.floor(this.viewHeight/this.cellSize)+1;j++)
	{

		if(this.data[i][j]==1)
			ctx.fillRect(i*this.cellSize -this.offsetX,j*this.cellSize -this.offsetY,this.cellSize ,this.cellSize );
	}
}

Nếu sử dụng ảnh nền để vẽ, bạn cần chia tọa độ và độ lớn của vùng ảnh cho tỉ lệ zoom. Với tỉ lệ zoom càng lớn, vùng ảnh được vẽ càng nhỏ và ngược lại:

ctx.drawImage(this.background,this.offsetX/this.zoom,this.offsetY/this.zoom,this.viewWidth/this.zoom,this.viewHeight/this.zoom,0,0,this.viewWidth,this.viewHeight);

Áp dụng cho các nhân vật trên bản đồ

Mỗi nhân vật hay đối tượng được thêm vào bản đồ cũng cần được thay đổi kích thước và vị trí tương ứng với tỉ lệ zoom. Ta có thể tính được tọa độ (left, top) mới của đối tượng bằng cách:

new_left = old_left/old_zoom*new_zoom
new_top = old_top/old_zoom*new_zoom

this.setZoom = function(zoom){
	if(this.zoom!=zoom)
	{
		this.size = BALL_SIZE*zoom;
		this.left = this.left/this.zoom*zoom;
		this.top = this.top/this.zoom*zoom;
		this.right = this.left + this.size;
		this.bottom = this.top + this.size;
		this.zoom = zoom;
	}
};

YinYangIt’s Blog

Advertisements

One thought on “Html5-Canvas: Phóng to/thu nhỏ game bằng nút cuộn chuột

Trả lờ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 Đăng xuất / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Đăng xuất / Thay đổi )

Connecting to %s