# 了解粒子事件

我们之前一起学习过,数据驱动实体具有定义事件和触发事件的功能。事实上,我们的粒子也可以定义和触发事件。在本节中,我们一起来学习如何定义和触发粒子的事件。

# 定义事件

目前,Snowstorm并不支持事件的定义和触发,因此,我们需要手动编辑JSON文件。事件和组件平级,是定义在模式标识符下的。

{
  "format_version": "1.10.0",
  "particle_effect": {
    "description": {
      "identifier": "tutorial_demo:some_particle",
      "basic_render_parameters": {
        "material": "particles_alpha",
        "texture": "textures/particle/particles"
      }
    },
    "events": {
      // 事件
    },
    "curves": {
      // 曲线
    },
    "components": {
      // 组件
    }
  }
}

events字段中,我们可以手动定义一些粒子的事件。和实体类似,每个粒子事件也是由一个对象组成的,对象的键名便是粒子的事件名。粒子事件也可以使用sequence来触发多个事件,或者使用randomize来加权随机触发一个事件。比如,我们可以分析如下杜撰的示例:

"events": {
  "<event_name_1>": {
    "sequence": [
      {
        "particle_effect": {
          "effect": "tutorial_demo:particle_1",
          "type": "emitter"
        },
        "sound_effect": {
          "event_name": "some.level.sound.event.name"
        }
      },
      {
        "particle_effect": {
          "effect": "tutorial_demo:particle_2",
          "type": "emitter"
        },
        "expression": "/* Some Molang Expression */"
      },
      {
        "sequence": [
          // 可以无限嵌套
        ]
      },
      {
        "randomize": [
          // 加权随机触发
        ]
      }
    ] // 可以写一个事件触发序列
  },
  "<event_name_2>": {
    "randomize": [
      {
        "weight": 1,
        "particle_effect": {
          "effect": "tutorial_demo:particle_2",
          "type": "particle"
        },
        "expression": "/* Another Molang Expression */"
      },
      {
        "weight": 1,
        "particle_effect": {
          "effect": "tutorial_demo:particle_4",
          "type": "particle_with_velocity"
        }
      }
    ] // 可以写一个加权随机触发
  },
  "<event_name_3>": {
    "particle_effect": {
      "effect": "tutorial_demo:particle_5",
      "type": "emitter_bound"
    } // 也可以直接写一个事件触发响应
  }
}

可以看到,这个事件的结构几乎和实体中的相一致,只是事件可以响应的内容有所不同。particle_effect用于在自己发射器的初始坐标处再生成另一个粒子,其中effect填写粒子的赋命名空间标识符,type填写生成的类型,可以填写emitteremitter_boundparticleparticle_with_velocity,分别代表着生成粒子的发射器、绑定生成粒子的发射器(即如果当前粒子绑定在了一个实体或定位器上,新粒子会继承这个绑定关系)、生成一个粒子实例和生成一个继承了当前发射器速度的粒子实例。

expression用于在触发事件时执行一个Molang表达式,一般用于更改变量的值。

sound_effect用于触发一个系统声音,或者称为存档声音事件。存档声音事件即是定义在资源包sounds.json中的声音,不过,对于粒子来说,只能触发定义在individual_event_sounds字段中的系统声音,即独立存档声音事件。比如,我们看原版的蜂蜜滴粒子的示例:

{
  "format_version": "1.10.0",
  "particle_effect": {
    "description": {
      "identifier": "minecraft:honey_drip_particle",
      "basic_render_parameters": {
        "material": "particles_alpha",
        "texture": "textures/particle/particles"
      }
    },
    "events": {
      "hit_ground": {
        "sound_effect": {
          "event_name": "block.beehive.drip"
        }
      }
    },
    "components": {
      // ...
      "minecraft:particle_motion_collision": {
        "coefficient_of_restitution": 0.1,
        "collision_drag": 10.0,
        "collision_radius": 0.01,
        "events": [
          {
            "event": "hit_ground",
            "min_speed": 0.5
          }
        ]
      }
      // ...
    }
  }
}

以及对应的sounds.json文件:

{
  "individual_event_sounds": {
    "events": {
      "block.beehive.enter": {
        "sound": "block.beehive.enter",
        "volume": 0.75,
        "pitch": [ 0.7, 0.8 ]
      },
      "block.beehive.exit": {
        "sound": "block.beehive.exit",
        "volume": 0.75,
        "pitch": [0.9, 1.1]
      },
      "block.beehive.shear": {
        "sound": "block.beehive.shear",
        "volume": 0.8,
        "pitch": [0.8, 1.0]
      },
      "block.beehive.work": {
        "sound": "block.beehive.work",
        "volume": 0.6,
        "pitch": 1.0
      },
      "block.beehive.drip": {
        "sound": "block.beehive.drip",
        "volume": 0.3,
        "pitch": [0.7, 0.9]
      } // 此处定义了block.beehive.drip系统声音
    }
  },
  "entity_sounds": {
    // ...
  }
  // ...
}

# 触发事件

粒子在多个组件中都能触发事件,其中最为主要的便是两个生命周期事件组件minecraft:emitter_lifetime_eventsminecraft:particle_lifetime_events

minecraft:emitter_lifetime_events组件为发射器的生命周期事件,其下具有creation_eventexpiration_eventtimelinetravel_distance_eventslooping_travel_distance_events五个字段,每个字段都能以特定的方式触发组件。

"minecraft:emitter_lifetime_events": {
  "creation_event": [ "<event_name>", ...],
  // "creation_event": "<event_name>",
  "expiration_event": [ "<event_name>", ...],
  // "expiration_event": "<event_name>",
  "timeline": {
    "some_time": [ "<event_name>", ... ],
    "another_time": "<event_name>"
  },
  "travel_distance_events": {
    "some_distance": [ "<event_name>", ... ],
    "another_distance": "<event_name>"
  },
  "looping_travel_distance_events": [
    {
      "distance": 1.0,
      "effects": [ "<effect_event_one>" ]
    },
    {
      "distance": 2.0,
      "effects": [ "<effect_event_two>" ]
    }
  ]

}

我们可以看到,创建事件creation_event和过期事件expiration_event都可以指定一个事件名或者以数组的形式指定多个事件名。时间轴timeline和移动距离事件travel_distance_events分别代表发射器经过特定时间或者走过特定距离后触发一个或多个事件。其中some_timeanother_timesome_distanceanother_distance都可以像动画的关键帧那样填写一个数字。循环移动距离事件looping_travel_distance_events用于定义每走过多远触发一次的事件,这样的事件必须是生成一个新的粒子效果的事件,也就这里触发的事件必须具有particle_effect字段的定义。

minecraft:particle_lifetime_events粒子的生命周期事件,不过其下只能定义创建事件creation_event、过期事件expiration_event和时间轴timeline。所有的语法是相同的。

至此,我们已经基本学习了粒子的大部分内容,接下来的一节,我们一起挑战创建一个烟花粒子,来完成我们本章的学习!