虽然目前几乎所有的webgame动画都使用Flash来实现,但是使用用JS来实现一场RPG的战斗动画,一直以来都不是什么难题。
去年我通过JS方式实现战斗引擎播放,效果也可以做的很绚丽,所有浏览器下,都测试通过,尚未发现卡的问题,但是,由于IE6下面,需要使用了VML(
由于将完成的一个游戏,是关卡玩法的游戏,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"]]);
😎 不错,如果有延时DEMO就更好了
呵呵,挺棒的,为什么不放个demo呢。wp有运行代码的插件。runcode 😀
我安装个试试。
把这个的演示版完整代码放出来看看吧