Cuộn bản đồ là chức năng không thể thiếu trong những game có bản đồ lớn vượt q kích thước khung nhìn (viewport) của màn hình. Bài viết này giúp bạn tìm hiểu một số phương pháp để tạo hiệu ứng, cuộn ảnh nền và bản đồ trong game.
1. Ảnh nền nhiều tầng
Một phương pháp đơn giản và tạo hiệu ứng đẹp là sử dụng ảnh nền nhiều tầng. Bằng cách cho mỗi tầng có tốc độ cuộn khác nhau, khung cảnh trong game trở nên có chiều sâu và thật hơn. Số lượng tầng này thường chỉ giới hạn từ 2 đến 3 và các tầng nằm bên dưới sẽ có tốc độ cuộn chậm hơn.
70 | P a g e
2. Cuộn giả
Bạn có thể thấy nhiều game có bản đồ rất lớn nhưng ảnh nền chỉ lặp đi lặp lại theo một mẫu duy nhất. Điều này được thực hiện bằng cách sử dụng một ảnh nền có kích thước nhỏ và được vẽ lặp đi lặp lại trên viewport. Tùy theo kích thước của ảnh nền này mà ta sử dụng phương pháp vẽ khác nhau.
Cách thông thường là sử dụng một ảnh nền có kích thước bằng viewport. Sau đó ta chia ảnh nền này thành hai phần theo chiều dọc dựa vào một đường phân cách:
- Cắt phần ảnh nền từ vị trí đường phân cách đến hết và vẽ lên viewport tại vị trí {0,0}.
- Cắt phần ảnh nền từ vị trí đầu tiên đến đường phân cách (phần cịn lại) và vẽ lên viewport tại vị trí tiếp nối với phần lúc nãy.
// position that divide the background into two parts offsetX++;
if(offsetX>width) offsetX = 0;
// draw the first part
ctx.drawImage(bgimg,offsetX,0,width-offsetX,height,0,0,width-offsetX,height); // the second part
ctx.drawImage(bgimg,0,0,offsetX,height,width-offsetX,0,offsetX,height);
3. … và cuộn thật
Với một bản đồ lớn, việc cuộn để giữ nhân vật chính của game ln ở giữa màn hình rất đơn giản. Ta có thể xác định được tọa độ (left và top) trên bản đồ sẽ được dùng để làm viewport bằng cách:
// inside Map object // obj = character
this.offsetX = obj.left - viewWidth/2; this.offsetY = obj.top - viewHeight/2;
Tuy nhiên việc thay đổi khung nhìn liên tục có thể khiến cho người chơi nhức mắt, mất tập trung và ảnh hưởng đến hiệu suất. Vì vậy ta áp dụng một giải phải là tạo một vùng giới hạn trong viewport gọi là “dead zone“. Khi nhân vật di chuyển nhưng vẫn nằm trong vùng này, viewport sẽ không bị thay đổi.
// inside Map object
var dx = obj.left - _map.offsetX; var dy = obj.top - _map.offsetY;
71 | P a g e
this.offsetX = obj.left - this.deadzone.left;
else if(dx+obj.size>this.deadzone.right)
this.offsetX = obj.right - this.deadzone.right;
if(dy<this.deadzone.top)
this.offsetY = obj.top - this.deadzone.top; else if(dy+obj.size>this.deadzone.bottom)
this.offsetY = obj.bottom - this.deadzone.bottom;
Xem Demo