GameDev – Tạo Amimated Sprite trong Html5 – Canvas

Baby Mario SpriteSprite là một phương pháp để tạo các đối tượng chuyển động từ một hình ảnh duy nhất. Bằng cách sắp xếp nhiều đối tượng theo thứ tự chuyển động, sprite giúp cho việc quản lý tài nguyên và xử lý hiệu quả hơn so với việc phải sử dụng nhiều tập tin ảnh riêng lẻ.

Xem Demo.

Một ảnh có thể gồm nhiều sprite có cùng kích thước hợp lại với nhau. Ví dụ hình dưới đây ta có thể thấy mỗi hàng là một sprite hiển thị chuyển động của nhân vật theo phương khác nhau. Vậy với mục đích là tạo lớp Sprite linh động, ta phải cho phép nó kết hợp được nhiều sprite với nhau và chuyển đổi qua lại giữa các sprite dễ dàng.

jasperrun

Mã nguồn của lớp AnimatedSprite:

var AnimatedSprite = function(data) {
	this.init(data);
	this.isFinished = false;
	this.currentSprite = null;
	this.currentFrame = 0;
	this.lastTick = 0;
};

AnimatedSprite.prototype = {
	start: function(){
		this.isFinished = false;
		this.currentFrame = 0;
	}
	init: function(data)
	{
		if(data){

			this.isLooping = data.isLooping;
			if(typeof this.isLooping!="boolean")
				this.isLooping = true;

			this.image = data.image;
			this.frameWidth = data.frameWidth;
			this.frameHeight = data.frameHeight || this.frameWidth;

			this.sprites = [];
			this.interval = data.interval;

			this.left = data.left;
			this.top = data.top;
			this.width = data.width || this.frameWidth;
			this.height = data.hegiht || this.frameHeight;

			this.onCompleted = data.onCompleted;
		}
	},
	addSprite: function(data){
		this.sprites[data.name]={
			name : data.name,
			startFrame : data.startFrame || 0,
			framesCount : data.framesCount || 1,
			framesPerRow : Math.floor(this.image.width/this.frameWidth)
		};

		this.currentSprite = this.currentSprite || this.sprites[data.name];
	},
	setSprite: function(name){
		if(this.currentSprite != this.sprites[name])
		{
			this.currentSprite = this.sprites[name];
			this.currentFrame = 0;
		}
	},
	update: function(){
		if(this.isFinished)
			return;
		var newTick = (new Date()).getTime();
		if(newTick-this.lastTick>=this.interval)
		{
			this.currentFrame++;

			if(this.currentFrame==this.currentSprite.framesCount)
			{
				if(this.isLooping)
					this.currentFrame=0;
				else
				{
					this.isFinished = true;
					if(this.onCompleted)
						this.onCompleted();
				}

			}
			this.lastTick = newTick;
		}

	},
	draw: function(context){

		if(this.isFinished)
			return;
		var realIndex = this.currentSprite.startFrame+this.currentFrame;
		var row = Math.floor(realIndex/this.currentSprite.framesPerRow);
		var col = realIndex % this.currentSprite.framesPerRow;

		context.drawImage(this.image,col*this.frameWidth,row*this.frameHeight,
		this.frameWidth,this.frameHeight,this.left,this.top,this.width,this.height);

	}
}

Để sử dụng, ta có thể tạo một lớp con của AnimatedSprite để cung cấp các chức năng di chuyển, kiểm tra va chạm. Ở đây tôi tạo một lớp Character thừa kế từ AnimatedSprite:

function Character(data){

	this.mapWidth = data.mapWidth;
	this.mapHeight = data.mapHeight;

	this.speedX = 0;
	this.speedY = 0;

	this.init(data);
}

Character.prototype = new AnimatedSprite();
Character.prototype.update = function(){

	var left = this.left+this.speedX;
	var top = this.top+this.speedY;
	var right = left+this.frameWidth;
	var bottom = top+this.frameHeight;

	if(left>0 && right<this.mapWidth)
		this.left = left;
	if(top>0 && bottom<this.mapHeight)
		this.top = top;
	AnimatedSprite.prototype.update.call(this);
};

Sau đó tạo đối tượng từ lớp Character ảnh bên trên để minh họa:

sprite = new Character({
	mapWidth: canvas.width,
	mapHeight: canvas.height,
	image: image,
	frameWidth: 32,
	frameHeight: 48,
	interval: 100,
	left: 10,
	top: 10,
});

sprite.addSprite({
	name: "walk_down",
	startFrame: 0,
	framesCount: 4
});

sprite.addSprite({
	name: "walk_left",
	startFrame: 4,
	framesCount: 4
});
sprite.addSprite({
	name: "walk_right",
	startFrame: 8,
	framesCount: 4
});
sprite.addSprite({
	name: "walk_up",
	startFrame: 12,
	framesCount: 4
});
sprite.setSprite("walk_left");
setInterval(function(){
	sprite.update();
	canvas.width = canvas.width;
	sprite.draw(context);
},1000/FPS);

YinYang’s Blog

Advertisements

5 thoughts on “GameDev – Tạo Amimated Sprite trong Html5 – Canvas

  1. Chào anh, em chưa hiểu rỏ lắm về prototype trong javascript, em thấy có lúc thì anh viết
    var AnimatedSprite = function(data) {
    ….
    };

    AnimatedSprite.prototype = {
    start: function(){
    …..
    }
    init: function(data)
    {
    …..
    }
    }

    Có lúc thì anh viết:
    function Cannon(map,x,y,color){

    }
    Cannon.prototype.draw = function(context){
    ….
    }

    Cannon.prototype.update = function(){
    ….
    }

    vậy hai cách viết này có gì khác nhau không anh? Nếu được anh có thể viết một bài về prototype nha anh.

    Phản hồi
  2. Javascript cho phép lập trình viên tạo một đối tượng và khai báo các thuộc tính của nó theo dạng cú pháp JSON. Tức là bạn có thể tạo một đối tượng point như sau:
    var point = {x: 1, y: 2}
    Tương đương với:
    var point = {};
    point.x = 1;
    point.y = 2;

    Ví dụ trong bài viết thì point chính là thuộc tính prototype. Tất cả các đối tượng javascript đều chứa thuộc tính này để lưu trữ các hàm hay thuộc tính instance của lớp.

    Phản hồi

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