虽然目前几乎所有的webgame动画都使用Flash来实现,但是使用用JS来实现一场RPG的战斗动画,一直以来都不是什么难题。

去年我通过JS方式实现战斗引擎播放,效果也可以做的很绚丽,所有浏览器下,都测试通过,尚未发现卡的问题,但是,由于IE6下面,需要使用了VML()方式来处理PNG透明问题,并且要注意IE6缓存图片BUG的问题,解决这两个问题之后,JS耗CPU较少,但占用内存明显增大。基于兼顾IE6用户的考虑等等,我仍然会选择Flash来完成战斗动画。

由于将完成的一个游戏,是关卡玩法的游戏,PVE部分,比较适合放到手机平台上当做手机单机游戏来玩,所以我考虑,是否使用HTML5来完成战斗引擎,针对Webkit内核的等等支持HTML5的浏览器,我们可以使用HTML5来完成战斗动画播放,则可以直接使用在Andriod、iOS、WP7等手机平台上。

由于我从05年开始,我使用JavaScript越来越多,其中大部分是使用Prototype,所以下面这个例子,是基于了Prototype JS的。

注:如Internet Explorer的一些浏览器,不支持canvas标签或本演示。的Chrome、Firefox、Safari、Opera浏览器的最新版本正常工作。

不使用HTML5来完成动画的时候,通过css改变背景图片的偏移量可以做出战斗动画。使用HTML5来完成,只需要在Canvas上面循环画出图片上面不同帧即可。

如下例子中,使用了如下图片,一个攻击动画:
战斗动画图片

最好的说明是实例:

配置动画参数:

 
var attack = { 
    name: 'attack',
    totalFrames: 10,
    loop: true,
    step: 4,
    width: 150,
    height: 150,
    sY: 0,
    sX: 0
}; //set initial animation set

角色动画:

 
/**
 * Sprite 系统,雏形
 *
 * @file_name   Sprite.js
 * @version     1.0
 * @author      黄新泽
 * @date        2011/1/14
 */

var	Sprite = Class.create({
	initialize : function(x, y, width, height, img, animation)//initialize sprite 
    {
        this.canvas = document.createElement('canvas'); //动画canvas

        this.canvas.setAttribute('width', width);
        this.canvas.setAttribute('height', height);
        this.ctx = this.canvas.getContext('2d'); //get canvas drawing context

		this.x = x; // X position of this sprite
		this.y = y; //Y position of this sprite
		this.animation = 0; //current animation for this sprite
		this.currentFrame = 0; //current animation frame for this sprite
        this.width = width;
        this.height = height;

		this.image = img; //image that is being drawn to the canvas
		this.currentStep = 0; //number of frames since this sprite's animation was updated
		this.isReady = true; //sprite has finished loading and can be used

        this.animation = animation;
    },

    drawImage: function()
    {   
        //draw image into sprite canvas
        this.ctx.clearRect(0, 0, this.width, this.height); //clear previous frame

        if(this.isReady)
        {
            //do not draw if sprite is not ready
            //calculate values for sprite based on animation
            var srcX = this.animation.sX + (this.currentFrame * this.animation.width);
            var srcY = this.animation.sY ;
            var srcWidth = this.animation.width;
            var srcHeight = this.animation.height;
            this.ctx.drawImage(this.image, srcX, srcY, srcWidth, srcHeight, 0, 0, srcWidth, srcHeight); //draw image
            this.stepSprite(); //advance animation
        }
    },

    stepSprite: function()
    {
        //advance animation based on animation speed (step value)
        if(this.currentStep >= this.animation.step)
        {
            this.currentStep = 0;
            this.currentFrame++;

            if(this.currentFrame >= this.animation.totalFrames)
            { 
                if(this.animation.loop)
                {
                    this.currentFrame = 0; //loop animation back to start
                }
                else
                {
                    this.currentFrame = this.animation.totalFrames -1;	//if loop not set, hold on final frame
                }
            }
        }
        else
        {
            this.currentStep++; //advance step counter if step limit not reached	
        }
    }
});

播放战斗动画:

 
var	FightAnimation = Class.create({

	canvas: 0, //main canvas object
	ctx: 0, //main canvas drawing context
	sprite: 0, //sprite object

	width: 900,
	height: 450,
	timer: 0,  //hold reference to game loop timer
	background: 0, //background image - for now is drawn right onto main canvas which is not ideal
	foreground: 0, //foreground object

	initialize: function(img)
    {
        //initialize FightAnimation
		this.canvas = document.getElementById('main');  //get canvas element from html
		this.ctx = this.canvas.getContext('2d'); //create main drawing canvas

		this.canvas.setAttribute('width', FightAnimation.width); //set attributes of canvas
		this.canvas.setAttribute('height', FightAnimation.height);

		this.sprite = new Sprite(0, 0, 150, 150, img, attack); //init sprite //create new Sprite object

        //document.body.insert(FightAnimation.sprite.canvas);
        this.timer = setInterval(this.drawFrame.bind(this), 40);
	},
	

	drawFrame: function()
    {
        //main drawing function
		this.ctx.clearRect(0, 0, this.width, this.height);  //clear main canvas

		//FightAnimation.ctx.drawImage(FightAnimation.background, 0, 0); // draw canvas background
		if(this.sprite)
        {
			this.sprite.drawImage(); //cause sprite to draw itself on its internal canvas
			this.ctx.drawImage(this.sprite.canvas, this.sprite.x, this.sprite.y);//draw sprite canvas onto main canvas
		}
	}
});

初始化战斗:

 
function startCanvas(e)
{
    new FightAnimation(img_res.successList['129_1_1'].img);  //initialize main Expermient object
}

document.on('img:oneloaded', startCanvas);  //处理进度条,........

var  img_res = ImgManage.getInstance();
img_res.addResourcesBag([["129_1_1", "/Images/actionicon/56/1/2.png"]]);

4 Replies to “HTML5游戏开发之一:动画制作

发表评论

电子邮件地址不会被公开。 必填项已用*标注