世界、发射器和粒子
我们在Canvas量子机关中,关键要把握好三个环节:“世界”、“投放器”还有“粒子”。世就是小颗粒们聚集的家园,投放器负责调整它们的特性,而粒子本身就是游戏中的各种东西,嬉戏玩耍于世界中。只要将三者完美配合,机关就能欢快地运转了。
你看,这个世界就像是一台巨大无比的发动机,里面全都是粒子在飞舞。只要这些小家伙待在这儿,他们就能被世界改变,感觉好好玩!想把粒子弄成什么形状?那就要看我们的发射器了。它决定粒子从哪个地方窜出来,长得多大,寿命多长之类的事情。另外,发射器还要处理那些挂掉的粒子,让整个机器运行得更顺溜。
重力、热气和风
咱们在游戏里加了个新功能,就是给那些小粒子装上了三个小伙伴儿:重力、热力和风力。这样一来,原本静静呆着的它们就开始跳舞!你看,由于重力让它们向上走,热力又喜欢高点儿的地方,风还能横着飞,这么多因素一加持,小粒子们就能走出各种各样的路线,真是有趣极了!
时间标志和全局更新
define(function(require, exports, module) { var Util = require('./Util'); var Launcher = require('./Launcher'); /** * 世界构造函数 * @param config * backgroundImage 背景图片 * canvas canvas引用 * context canvas的context * * time 世界时间 * * gravity 重力加速度 * * heat 热力 * heatEnable 热力开关 * minHeat 随机最小热力 * maxHeat 随机最大热力 * * wind 风力 * windEnable 风力开关 * minWind 随机最小风力 * maxWind 随机最大风力 * * timeProgress 时间进步单位,用于控制时间速度 * launchers 属于这个世界的发射器队列 * @constructor */ function World(config){ //太长了,略去细节 } World.prototype.updateStatus = function(){}; World.prototype.timeTick = function(){}; World.prototype.createLauncher = function(config){}; World.prototype.drawBackground = function(){}; module.exports = World; });
我们在引擎里加个计时器标记,就是为了保证状态变化比如粒子的生生死死和时间效果的流利。这样以后制作瞬移或者回溯之类的功能就能简单点。当然,也别忘了外面还有个程序,留着放映游戏整体情况的口子:时不时去看看发射器需不需要update;弄点新粒子出来,把所有的都画上。
/** * 循环触发函数 * 在满足条件的时候触发 * 比如RequestAnimationFrame回调,或者setTimeout回调之后循环触发的 * 用于维持World的生命 */ World.prototype.timeTick = function(){ //更新世界各种状态 this.updateStatus(); this.context.clearRect(0,0,this.canvas.width,this.canvas.height); this.drawBackground(); //触发所有发射器的循环调用函数 for(var i = 0;i<this.launchers.length;i++){ this.launchers[i].updateLauncherStatus(); this.launchers[i].createGrain(1); this.launchers[i].paintGrain(); } };
世界状态更新和发射器生成
为了把事情处理好,得在线搞点新粒子呀。这么一来,后面的事就顺利多了。
World.prototype.updateStatus = function(){ this.time+=this.timeProgress; this.wind = Util.randomFloat(this.minWind,this.maxWind); this.heat = Util.randomFloat(this.minHeat,this.maxHeat); };
发射器属性和基因
World.prototype.createLauncher = function(config){ var _launcher = new Launcher(config); this.launchers.push(_launcher); };
每根小发器都是独一无二的,位置、风速和温度各不相同。还有个秘密告诉你,每个小发器其实都有自己的「基因」,作用就在于他们是怎样变身为小粒的。不过你可能想不到,给这些小发器加入更多的基因的话,出生后的宝宝就会不像原来那么陌生~
粒子状态与绘制
每颗小颗粒就像发动机里的螺钉,有自己的特点–如位子、速度、大小,甚至是寿命!下面要做的就是算出这些颗粒下一步怎么炸开宇宙,再把它们留在墙上形成酷炫的效果。整件事关键就在于不停更新每个颗粒的现状,这样整个画面才能行云流水般顺畅
define(function (require, exports, module) { var Util = require('./Util'); var Grain = require('./Grain'); /** * 发射器构造函数 * @param config * id 身份标识用于后续可视化编辑器的维护 * world 这个launcher的宿主 * * grainImage 粒子图片 * grainList 粒子队列 * grainLife 产生的粒子的生命 * grainLifeRange 粒子生命波动范围 * maxAliveCount 最大存活粒子数量 * * x 发射器位置x * y 发射器位置y * rangeX 发射器位置x波动范围 * rangeY 发射器位置y波动范围 * * sizeX 粒子横向大小 * sizeY 粒子纵向大小 * sizeRange 粒子大小波动范围 * * mass 粒子质量(暂时没什么用) * massRange 粒子质量波动范围 * * heat 发射器自身体系的热气 * heatEnable 发射器自身体系的热气生效开关 * minHeat 随机热气最小值 * maxHeat 随机热气最小值 * * wind 发射器自身体系的风力 * windEnable 发射器自身体系的风力生效开关 * minWind 随机风力最小值 * maxWind 随机风力最小值 * * grainInfluencedByWorldWind 粒子受到世界风力影响开关 * grainInfluencedByWorldHeat 粒子受到世界热气影响开关 * grainInfluencedByWorldGravity 粒子受到世界重力影响开关 * * grainInfluencedByLauncherWind 粒子受到发射器风力影响开关 * grainInfluencedByLauncherHeat 粒子受到发射器热气影响开关 * * @constructor */ function Launcher(config) { //太长了,略去细节 } Launcher.prototype.updateLauncherStatus = function () {}; Launcher.prototype.swipeDeadGrain = function (grain_id) {}; Launcher.prototype.createGrain = function (count) {}; Launcher.prototype.paintGrain = function () {}; module.exports = Launcher; });
试了好多回,最后终于找到了一款功能强大的Canvas粒子引擎,只需三步就可以搞定啦——创建一个世界、放上发射器以及无数可爱的小颗粒。有了这些元素,你将会看到各种炫酷的运动轨迹和逼真的动态效果,真是太棒了!而且,各个部分搭配得天衣无缝,构造成的就是一个既精致又酷炫的微观世界。
Launcher.prototype.createGrain = function (count) { if (count + this.grainList.length = this.maxAliveCount && count + this.grainList.length > this.maxAliveCount) { //光是旧的粒子数量还没能达到最大限制 //新建了count个加上旧的超过了最大数额限制 count = this.maxAliveCount - this.grainList.length; } else { count = 0; } for (var i = 0; i < count; i++) { var _rd = Util.randomFloat(0, Math.PI * 2); var _grain = new Grain({/*粒子配置*/}); this.grainList.push(_grain); } };
评论0