Ring of Fire particle system

This tutorial builds on the particle systems tutorial to create a ring of fire around the Warrior model using a Scene.ParticleRingEmitter. The following topics are covered in this tutorial:

  1. Creating a project
  2. Setup of model, camera and render loop
  3. Ring of Fire

The tutorial's code files and media files are installed along with Ginjo-Builder and can be accessed from the 'Project' window that is shown when the editor starts. This tutorial is called '16_RingOfFire' in the 'Tutorials' tab.

1. Creating a project

First we create a project and compiler options XML file. (See Render loop for a more detailed description of creating a project.)

  1. Create a new project through the Project menu.
  2. Right click on project's top level tree node named "New GBP(Unsaved)" and select Rename folder. Rename the folder to "Fire".
  3. Save the project as "RingOfFire.gbp" from the Project menu.
  4. Add a new file to the project tree and save it as "FireEffect.gbc"
  5. Add a new file to the project tree and save it as "Fire.xml". (The XML file must have the same name as the top level tree node.)

Open "Fire.xml" and just like in Render loop add the <exe> and <startup> elements. We will also import the GB namespace so we don't have to type it out every time. (For the full list of XML tags see Compiler options.)

<?xml version="1.0" encoding="utf-8"?>
<root>
   <exe path=".\game.exe" />
   <startup name="FireEffect.main" />
   
   <ImportSymbols>
      <namespace name="GB"  />
   </ImportSymbols>
</root>

2. Setup of model, camera and render loop

In our XML file we specified the startup function as "FireEffect.main". Double-click on "FireEffect.gbc" in the project tree to open it, and add the following function, called "main". (When you run your program this is the function where execution starts.) Initialize the Irrlicht 3D engine, add the Warrior model, a Maya camera from the cameras tutorial and create a render loop as in the Render loop tutorial. In this tutorial we do not have any lights, thus the Lighting material flag of the model must be turned to false. (Otherwise the model will be completely black.)

function main(var:string cmdArgs[]) returns Int32
{
   var:gb.IrrlichtCreationParameters options=new gb.IrrlichtCreationParameters()
   //Without anti-aliasing our model edges would be jagged 
   options.AntiAliasing=255
   //Tell Irrlicht to use OpenGL for graphics
   options.DriverType=gb.video.DriverType.OpenGL
   //Turn off logging, we won't be using it for now
   options.LoggingLevel=gb.LogLevel.None
   
   var:gb.IrrlichtDevice engine = gb.IrrlichtDevice.CreateDevice(options)
   //Also set our window's title
   engine.SetWindowCaption('Event handling')
   
   var:video.VideoDriver driver=engine.VideoDriver
   var:Scene.SceneManager smgr=engine.SceneManager

   //add camera 
   var:scene.CameraSceneNode Camera= smgr.AddCameraSceneNodeMaya()

   //load model from relative path ..\media\warrior.x
   var:scene.AnimatedMesh WarriorMesh = smgr.GetMesh('..\media\warrior.x')
   //add model to scene
   var:Scene.AnimatedMeshSceneNode Warrior
   Warrior = smgr.AddAnimatedMeshSceneNode(WarriorMesh)

   if(!isNull(Warrior)){
      Warrior.AnimationSpeed = 20
      Warrior.Scale = new core.Vector3Df(20)
      Warrior.SetMaterialFlag(video.MaterialFlag.Lighting, false)
      Warrior.SetFrameLoop(21,119) //stand animation loop
      camera.Target = Warrior.Position + new core.Vector3Df(0,20,0)
   }
   
   var:video.Color background=new video.Color(160, 160, 160)
   while (engine.Run()){
      driver.BeginScene(video.ClearBufferFlag.All, background)
      smgr.DrawAll()
      driver.EndScene()
   }
}

At this point we have the results from the SetFrameLoop animation tutorial with the 'stand' animation of the model playing in a loop.

3. Ring of Fire

In the particle systems tutorial we specified the model as the parent node of the particle system. However, here we pass in null for the second parameter of AddParticleSystemSceneNode. Thus, the position of the particle system is in world coordinates and it does not move or rotate with the model. Note that the last parameter in our ParticleSystem.CreateRingEmitteris the direction vector. It determines not only the direction the particles are emitted in, but also their speed. To create a ring emitter modify the Warrior's code block to the following:

if(!isNull(Warrior)){
  Warrior.AnimationSpeed = 20
  Warrior.Scale = new core.Vector3Df(20)
  Warrior.SetMaterialFlag(video.MaterialFlag.Lighting, false)
  Warrior.SetFrameLoop(21,119) //stand animation loop
  camera.Target = Warrior.Position + new core.Vector3Df(0,20,0)
  
  var:scene.ParticleSystemSceneNode ParticleSystem = smgr.AddParticleSystemSceneNode(false, null)
  ParticleSystem.SetMaterialFlag(gb.video.MaterialFlag.Lighting, false)
  ParticleSystem.SetMaterialTexture(0, driver.GetTexture('..\media\fireball.bmp'))
  ParticleSystem.SetMaterialType(video.MaterialType.TransparentAddColor)

  var:scene.ParticleRingEmitter Emitter= ParticleSystem.CreateRingEmitter(Warrior.Position,20, 4, new core.Vector3Df(0,0.01,0))
  Emitter.MinLifeTime=500
  Emitter.MaxLifeTime=1000
  Emitter.MinParticlesPerSecond=1800
  Emitter.MaxParticlesPerSecond=2500
  ParticleSystem.Emitter=Emitter
}

Note that you can use the IntelliDoc Symbol Info feature to look-up symbol types and definitions. The 'lightbulb' button on the toolbar looks-up the symbol type for the current cursor location and displays it in a tooltip. Pressing F1 also shows the tooltip.

When you run the code you should see the following: