Html5 – Canvas: Viết game bắn đại bác – part2

Cannon MovingTiếp theo phần 1, phần này tôi sẽ tập trung hướng dẫn về cannon và đạn, bao gồm: trọng lực, gió, tầm sát thương và di chuyển cannon. Bởi vì chỉ có một viên đạn được bắn ra bởi các cannon trong cùng lúc, ta sẽ chỉ cần tạo duy nhất một viên đạn để sử dụng chung cho tất cả cannon. Bằng việc tách riêng đối tượng này ra khỏi lớp Cannon, ta sẽ dễ đàng quản lý va chạm và các ảnh hưởng khác từ môi trường (map).

Trọng lực và Gió

Trong dạng game này, đạn khi được bắn ra sẽ chịu tác động cùng lúc của 3 loại lực là: lực bắn, trọng lực và gió. Mỗi lực này có thể được minh họa bởi một vector (Lực bắn đã được giới thiệu trong phần trước). Tại mỗi thời điểm khi đạn bay trong không gian, vị trí mới của nó sẽ được tính bằng cách dùng vị trí hiện tại cộng với vector tổng của 3 lực này. Việc tính toán này rất đơn giản và thực tế, và như vậy ta có được phương thức update của đạn:

Ball.prototype.update = function(wind){
    this.speedY += GRAVITY+wind.y;
	this.speedX += wind.x;

	this.cx += this.speedX;
    this.cy += this.speedY;
    if(this.cx < this.minX || this.cx > this.maxX ||
        this.cy < this.minY this.cy > this.maxY)
        return true;
    return false;
}

Lưu ý: Bạn sẽ thấy rằng tốc độ đạn bay quá nhanh có thể khiến cho việc kiểm tra va chạm không chính xác (do trong game là đạn “biến” từ nơi này đến nơi khác). Vì vậy cần giảm tốc độ đạn lại và tăng FPS lên một giá trị thích hợp. Để tạo gió, tôi sử dụng một vector với hai giá trị x,y thay đổi ngẫu nhiên sau một khoảng thời gian khoảng 20 giây. map.js:

var lastTick = 0;
// change wind direction every 20 seconds
var windChangeInterval = 20000;
this.wind = {x: 0,y: 0};

this.update = function(){
	var newTick = (new Date()).getTime();
	if(newTick-lastTick>=windChangeInterval)
	{
		lastTick = newTick;

		this.wind.x = (Math.random()-Math.random())/30;
		this.wind.y = (Math.random()-Math.random())/30;
	}
};

Phạm vi sát thương của đạn

Trong lớp Ball, tôi tạo thêm một thuộc tính là damageRangeđể xác định phạm vi sát thương của đạn. Và nếu mỗi loại xe có sức mạnh khác nhau, chỉ cần gán giá trị tương ứng cho thuộc tính damageRange của đạn. Ta cần sửa lại lớp Map để nó thực hiện đúng việc kiểm tra va chạm với đạn:

Map.prototype.collide = function(ball){
	var x = Math.floor(ball.cx);
	var y = Math.floor(ball.cy);
	if(this.contain(x,y))
	{
		context.save();
		context.globalCompositeOperation = "destination-out";
		context.fillStyle = "rgba(0,0,0,1)";
		context.beginPath();
		context.arc(x,y,ball.damageRange,0,Math.PI*2,true);
		context.fill();
		context.restore();
		imageData = context.getImageData(0,0,width,height);
		return true;
	}
	return false;
}

Di chuyển Cannon

Do có địa hình phức tạp, việc di chuyển cannon sẽ tương đối phức tạp và còn tùy thuộc vào hình dạng của nó. Việc cần quan tâm ở đây là cách để cannon có thể đi lên địa hình dốc vừa phải. Một mẹo nhỏ mà tôi làm ở đây là sử dụng cách “nhảy cóc” thay vì đi. Như vậy mỗi bước đi theo chiều ngang tôi cũng đồng thời nâng cao vị trí của cannon hơn một chút. Nếu cannon đi xuống dốc, nó sẽ rơi xuống vị trí thấp hơn (nhờ phương thức update()); nếu cannon đi lên dốc, nó sẽ ở vị trí cao hơn. Đối với dốc có độ nghiêng lớn, ta sẽ kiểm tra một tọa độ bên trái (hoặc phải tùy theo hướng di chuyển) xem nó có chạm vào mặt địa hình không. Nếu có, ta sẽ không cho phép cannon di chuyển theo hướng đó.

Cannon.prototype.handleInputs = function(e){
	if(this.isFalling || this.isDeath)
		return;
	switch(e.keyCode)
	{
		case 37: // left arrow
			this.move(-SPEED);
			break;
		case 39: // right arrow
			this.move(SPEED);
			break;
		default:
		 break;
	}
}
Cannon.prototype.move = function(speedX){
	if(this.isDeath)
		return;
	var px;
	if(speedX<0) // move left
		px = this.left;
	else
		px = this.right;

	if(!this.map.contain(px,this.cy))
	{
		this.cy -= 1;
		this.cx += speedX;
	}
}

Html5 - canvas - Cannon Game Demo - p2

Trong phần tới tôi sẽ hướng dẫn tạo lifebar (HP), hỗ trợ nhiều người chơi và trang trí cho game bằng một vài hiệu ứng.

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