• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com专业计算机教程网站
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • html/xhtml
  • html5
  • CSS
  • XML/XSLT
  • Dreamweaver教程
  • Frontpage教程
  • 心得技巧
  • bootstrap
  • vue
  • AngularJS
  • HBuilder教程
  • css3
  • 浏览器兼容
  • div/css
  • 网页编辑器
  • axure
您的位置:首页 > 网页设计 >html5 > 使用HTML5 canvas实现一个简单的粒子引擎代码实例

使用HTML5 canvas实现一个简单的粒子引擎代码实例

作者:匿名 字体:[增加 减小] 来源:互联网 时间:2018-12-03

本文主要包含HTML5 ,canvas,粒子引擎等相关知识,匿名希望在学习及工作中可以帮助到您

前言

好吧,说是“粒子引擎”还是大言不惭而标题党了,离真正的粒子引擎还有点远。废话少说,先看demo

本文将教会你做一个简单的canvas粒子制造器(下称引擎)。

世界观

这个简单的引擎里需要有三种元素:世界(World)、发射器(Launcher)、粒子(Grain)。总得来说就是:发射器存在于世界之中,发射器制造粒子,世界和发射器都会影响粒子的状态,每个粒子在经过世界和发射器的影响之后,计算出下一刻的位置,把自己画出来。

世界(World)

所谓“世界”,就是全局影响那些存在于这这个“世界”的粒子的环境。一个粒子如果选择存在于这个“世界”里,那么这个粒子将会受到这个“世界”的影响。

发射器(Launcher)

用来发射粒子的单位。他们能控制粒子生成的粒子的各种属性。作为粒子们的爹妈,发射器能够控制粒子的出生属性:出生的位置、出生的大小、寿命、是否受到“World”的影响、是否受到"Launcher"本身的影响等等……

除此之外,发射器本身还要把自己生出来的已经死去的粒子清扫掉。

粒子(Grain)

最小基本单位,就是每一个骚动的个体。每一个个体都拥有自己的位置、大小、寿命、是否受到同名度的影响等属性,这样才能在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;
});

大家都知道,画动画就是不断得重画,所以我们需要暴露出一个方法,提供给外部循环调用:

/**
 * 循环触发函数
 * 在满足条件的时候触发
 * 比如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();
    }
};

这个timeTick方法在外部循环调用时,每次都做着这几件事:

  1. 更新世界状态

  2. 清空画布重新绘制背景

  3. 轮询全世界所有发射器,并更新它们的状态,创建新的粒子,绘制粒子

那么,世界的状态到底有哪些要更新?

显然,每一次都要让时间往前增加一点是容易想到的。其次,为了让粒子尽可能动得风骚,我们让风和热力的状态都保持不稳定——每一阵风和每一阵热浪,都是你意识不到的~

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;

});

发射器要负责生孩子啊,怎么生呢:

 Launcher.prototype.createGrain = function (count) {
        if (count + this.grainList.length <= this.maxAliveCount) {
            //新建了count个加上旧的还没达到最大数额限制
        } else if (this.grainList.length >= this.maxAliveCount &&
            count + this.grainList.length > this.maxAlive
  


 

您可能想查找下面的文章:

  • HTML5的本地存储
  • Define charset for HTML5 Doctype
  • HTML5 canvas如何绘制动态径向渐变
  • 如何使用HTML5 Canvas绘制动态线性渐变
  • HTML5 canvas如何实现马赛克的淡入淡出效果(代码)
  • HTML5 canvas中如何绘制图像
  • 如何使用HTML5 canvas实现图像的马赛克
  • html5 canvas实现简单的双缓冲
  • HTML5 Canvas 图形组合是如何实现的?附代码
  • HTML5 figure标签是什么意思?HTML5 figure标签的使用方法详解

相关文章

  • 2018-12-03html5的web存储
  • 2018-12-03分享HTML5实现弹出框的效果示例
  • 2018-12-03前缀data-属性和dataset的使用方法
  • 2018-12-03关于HTML5 Placeholder新标签低版本浏览器下不兼容的问题分析及解决办法 _html5教程技巧
  • 2018-12-03HTML5边玩边学(五)-图像、图案和字体
  • 2018-12-03IE10 Error.stack 让脚本调试更加方便快捷_html5教程技巧
  • 2018-12-03HTML5 Canvas来绘制图形
  • 2018-12-03介绍HTML5+Canvas调用手机拍照功能实现图片上传(下篇)
  • 2018-12-03HTML5实战与剖析之自定义数据属性(dataset)
  • 2018-12-03HTML5无刷新改变当前url

文章分类

  • html/xhtml
  • html5
  • CSS
  • XML/XSLT
  • Dreamweaver教程
  • Frontpage教程
  • 心得技巧
  • bootstrap
  • vue
  • AngularJS
  • HBuilder教程
  • css3
  • 浏览器兼容
  • div/css
  • 网页编辑器
  • axure

最近更新的内容

    • 用HTML5的canvas实现一个炫酷时钟效果
    • 写这样一个求婚网页,需要具备什么IT技能?
    • 详细介绍HTML5模拟齿轮动画的代码示例详情
    • Canvas and Drawables 翻译第一集
    • HTML5实战与剖析之是否从主屏幕图标进入的网站
    • html5移动页面如何自适应屏幕?html5页面自适应手机屏幕的四种方法
    • HTML5+Canvas+CSS3实现齐天大圣孙悟空腾云驾雾效果_html5教程技巧
    • H5学习之旅-H5的块标签的使用(9)
    • 在移动HTML5页面input类型采用number无法控制长度,以及右边显示难看的加减按钮
    • 深入解析HTML5 内联框架--iFrame

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有