HTML5游戏开发之一:动画制作

虽然目前几乎所有的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"]]);

Related posts:

  1. 去掉JW Player水印及右键官方菜单 之前为葱哥修改编译了去掉JW Player水印及右键官方菜单JW Player, 今天想弄个视频,就又去下载了修改了下: 修改方法: 去掉Logo水印; 在文件“/com/longtailvideo/jwplayer/view/View.as ”中找到“_logoLayer.addChild(_logo);”将其注释掉即可。 去掉右键about官网地址链接。 在文件“/com/longtailvideo/jwplayer/view/RightclickMenu.as...
  2. Android and HTML5 开发手机应用 作为一个WEB开发者,HTML5让我兴奋,因为它可以将桌面应用程序功能带入浏览器中。但在国内,看着到处横行的IE8版本以下的浏览器,觉得到能大规模使用HTML5技术的那天,还遥遥无期。但面对iOS及Android等平台的手机用户越来越多,基于Webkit内核的移动浏览器一定能让HTML5先大规模应用起来。这将对对移动 Web 应用程序开发具有重大影响。 作为非常看好未来手机网络的我,也在一直研究Android平台的应用的开发,也许是因为自己更熟悉HTML及CSS、JS,并受到之前使用HTML和VC开发程序的影响,我也更愿意使用HTML来做Android程序的UI…. 09年,在开发《华夏风云》游戏的时候,使用了基于Google Gear插件来做了很多离线应用,可惜Gear已经不在更新开发,被HTML5取代。下面介绍基于HTML 5 的Web 应用程序的本地存储,不再废话,例子说明一切。  ...

发表评论?

4 条评论。

  1. :cool: 不错,如果有延时DEMO就更好了

  2. 呵呵,挺棒的,为什么不放个demo呢。wp有运行代码的插件。runcode :grin:

  3. 我安装个试试。

  4. 把这个的演示版完整代码放出来看看吧

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>