Thứ ba, ngày 6 tháng 12 năm 2016

HTML5 – Canvas 2D: Hiệu ứng bóng chuyển động và phản xạ – part 1

Ngày đăng: 18/4/2012, 8:26:49AM | Lượt xem: 1,736
Hot!

Một ví dụ đơn giản để khi làm quen với đồ họa và chuyển động trong lập trình là viết một ví dụ bóng nảy bên trong một vùng cửa sổ (canvas). Một quả bóng sẽ được vẽ bên trong canvas và chuyển động theo một hướng xác định. Khi chạm bất kì thành tường nào, bóng sẽ đổi hướng chuyển động tùy theo hướng di chuyển.

HTML5 - Canvas 2D - Simple Bouncing ballMột ví dụ đơn giản để khi làm quen với đồ họa và chuyển động trong lập trình là viết một ví dụ bóng nảy bên trong một vùng cửa sổ (canvas). Một quả bóng sẽ được vẽ bên trong canvas và chuyển động theo một hướng xác định. Khi chạm bất kì thành tường nào, bóng sẽ đổi hướng chuyển động tùy theo hướng di chuyển.

Xem Demo.

Cơ bản

Ta xác định hai giá trị speedX và speedY tương ứng với tốc độ di chuyển theo phương ngang và dọc của trái bóng. Hướng di chuyển của bóng phụ thuộc vào giá trị âm hoặc dương của speedX và speedY.

Trong ví dụ này, thành tường là các biên của canvas và chỉ có hai phương là ngang và dọc. Nguyên lý hoạt động rất đơn giản: khi bóng tiếp xúc với biên dọc của canvas, ta sẽ đổi chiều của speedY và với biên ngang ta sẽ đổi chiều của speedX.

Trong lớp Ball sau, tôi sẽ bổ sung thêm các thuộc tính right, bottom để tiện khi kiểm tra va chạm. Hai thuộc tính cx và cy là vị trí tâm của bóng và sẽ được khởi tạo ngẫy nhiên sao cho nó luôn nằm hoàn toàn bên trong canvas.

Ball.js:

function Ball(mapWidth, mapHeight){
	this.mapWidth = mapWidth;
	this.mapHeight = mapHeight;

	this.radius = 20;
	this.speedX = 3;
	this.speedY = 3;

	this.cx = Math.floor(Math.random()*(this.mapWidth-2*this.radius)) + this.radius;
	this.cy = Math.floor(Math.random()*(this.mapHeight-2*this.radius)) + this.radius;

}
Ball.prototype.draw = function(context){
	context.beginPath();
	context.fillStyle = "red";
	context.arc(this.cx,this.cy,this.radius,0,Math.PI*2,true);
	context.closePath();
	context.fill();
}
Ball.prototype.move = function(){
	this.cx += this.speedX;
	this.cy += this.speedY;

	this.left = this.cx - this.radius;
	this.top = this.cy - this.radius;
	this.right = this.cx + this.radius;
	this.bottom = this.cy + this.radius;
}
Ball.prototype.checkCollision = function(shapes) {

	if(this.left <= 0 || this.right >= this.mapWidth) this.speedX = -this.speedX;
	if(this.top <= 0 || this.bottom >= this.mapHeight) this.speedY = -this.speedY;

}

Sample.html:

<html>
<head>

<script src="ball.js"></script>
<script>

var _canvas;
var _context;
var _ball;

function draw(){
	_context.clearRect(0,0,_canvas.width,_canvas.height);
	_ball.draw(_context);
}
function update(){
	_ball.move();
	_ball.checkCollision();
	draw();
}

window.onload = function(){

	var interval = 10;
	_canvas = document.getElementById("canvas");
	_context = _canvas.getContext("2d");
	_ball = new Ball(_canvas.width,_canvas.height);

	setInterval("update()",interval);
}
</script>
</head>
<body>
   <canvas id="canvas" width="400px" height="300px" style="border: 1px solid gray;"></canvas>
</body>
</html>

Thêm hiệu ứng bóng di chuyển

Để ví dụ không quá đơn điệu, tôi sẽ thêm các ảnh bóng mờ di chuyển phía sau trái bóng chính. Tôi sẽ lưu các vị trí bóng di chuyển qua vào một mảng có tối đa 10 phần tử và vẽ ra canvas trong hàm draw(). Phương thức Ball.draw() cần chỉnh sửa một chút để cho phép nhận tham số alpha xác định độ mờ đục. Tham số alpha này có giá trị nằm giữa đoạn 0 và 1:

Ball.prototype.draw = function(context,alpha){
	if(!alpha)
		alpha = 255;
	context.beginPath();
	context.fillStyle = "rgba(255, 100, 100," + alpha + ")";
	context.arc(this.cx,this.cy,this.radius,0,Math.PI*2,true);
	context.closePath();
	context.fill();

}

Để các trái bóng không nằm quá sát nhau, tôi chỉ thực hiện lưu vị trí của bóng sau mỗi 5 lần bóng di chuyển hay sau mỗi 5 lần phương thức update() được gọi. Phương thức traceBall() sau sẽ tạo ra một đối tượng Ball mới với hai giá trị cx và cy lấy từ trái bóng chính và lưu vào mảng _balls. Khi chiều dài của mảng _balls vượt quá 10, tôi dùng phương thức Array.splice() để cắt đi phần tử nằm ở đầu mảng:

function traceBall(ball){
	var b = new Ball;
	b.cx = ball.cx;
	b.cy = ball.cy;

	_balls.push(b);
	if(_balls.length>10)
		_balls.splice(0,1);
}

Kết quả:

HTML5 - Canvas 2D - Simple Bouncing ball

Mã nguồn hoàn chỉnh

Ball.js:

function Ball(mapWidth, mapHeight){
	this.mapWidth = mapWidth;
	this.mapHeight = mapHeight;
	this.radius = 20;
	this.speedX = 3;
	this.speedY = 3;

	this.cx = Math.floor(Math.random()*(this.mapWidth-2*this.radius)) + this.radius;
	this.cy = Math.floor(Math.random()*(this.mapHeight-2*this.radius)) + this.radius;
}
Ball.prototype.draw = function(context,alpha){
	if(!alpha)
		alpha = 255;
	context.beginPath();
	context.fillStyle = "rgba(255, 100, 100," + alpha + ")";
	context.arc(this.cx,this.cy,this.radius,0,Math.PI*2,true);
	context.closePath();
	context.fill();
}
Ball.prototype.move = function(){
	this.cx += this.speedX;
	this.cy += this.speedY;

	this.left = this.cx - this.radius;
	this.top = this.cy - this.radius;
	this.right = this.cx + this.radius;
	this.bottom = this.cy + this.radius;
}
Ball.prototype.checkCollision = function(shapes) {

	if(this.left <= 0 || this.right >= this.mapWidth) this.speedX = -this.speedX;
	if(this.top <= 0 || this.bottom >= this.mapHeight) this.speedY = -this.speedY;
}

Sample.html:

<html>
<head>

<script src="ball.js"></script>
<script>

var _canvas;
var _context;
var _ball;
var _balls = [];
var _counter = 0;
function draw(){

	_context.clearRect(0,0,_canvas.width,_canvas.height);

	for(var i = 0; i < _balls.length; i++){
		_balls[i].draw(_context,(i+1)/10);
	}
	_ball.draw(_context);
}
function update(){
	_counter++;
	if(_counter == 5){
		traceBall(_ball);
		_counter = 0;
	}
	draw();
	_ball.move();
	_ball.checkCollision();

}
function traceBall(ball){
	var b = new Ball;
	b.cx = ball.cx;
	b.cy = ball.cy;

	_balls.push(b);
	if(_balls.length>10)
		_balls.splice(0,1);
}
window.onload = function(){

	var interval = 10;
	_canvas = document.getElementById("canvas");
	_context = _canvas.getContext("2d");
	_ball = new Ball(_canvas.width,_canvas.height);

	window.setInterval(function(){
		update();
	},interval);

}
</script>
</head>
<body>
   <canvas id="canvas" width="400px" height="300px" style="border: 1px solid gray;"></canvas>
</body>
</html>

YinYang’s Programming Blog

 Chia sẻ qua: 
Hot!
Ý kiến bạn đọc

These items will be permanently deleted and cannot be recovered. Are you sure?

Gallery

image

Maecenas viverra rutrum pulvinar

Maecenas viverra rutrum pulvinar! Aenean vehicula nulla sit amet metus aliquam et malesuada risus aliquet. Vestibulum rhoncus, dolor sit amet venenatis porta, metus purus sagittis nisl, sodales volutpat elit lorem…

Read more

Text Links

Thiết kế logo chuyên nghiệp Insky
DAFABET
W88 w88b.com/dang-ky-tai-khoan-w88
W88
Copyright © 2011 - 2012 vietshare.vn by phamkhuong102@gmail.com doanhkisi2315@gmail.com. All rights reserved.