Authors:

Targeted audience:

Required reading:

Required knowledge:

Explains:

Introduction

It is assumed that you already have the DLL project name 'Tutorial' set up and opened in Developer Studio. If you don't, consult How to Create a new Entity Package tutorial on how to create one.

The Blob

What we will try to do here is just make one simple class with some basic behavior and movement. Our Blob will be just a stupid piece of jelly jumping around.

Creating and Preparing the Entity Source File

Make a new file named 'Blob.es' (in the project directory e.g. 'Tutorial\Blob.es') and add it to the project. Since entity sources are not generically supported by VisualC++, select 'C++ Source File' for the file type. The file should be automatically added to the 'Classes' folder of the project.

Note that the project must be in the Sources directory, or it will not be compiled properly.
There is no default action to build .es files, so you have to add a custom build for that. Go to Project/Settings, select the 'Blob.es' file and choose 'Custom Build' tab.

For 'All configurations', set:

'Description' to:
Tutorial/$(InputName).es
'Commands' to:
cd ..\
ecc Tutorial/$(InputName).es
and 'Outputs' to:
$(InputName).cpp

Now, the file has a custom build action which will compile it using Ecc and make cpp source files out of it.

Writing Initial Source

Empty entity source will not compile with Ecc. You must give it some basic skeleton to make it pass syntax and semantic checking.
For detailed information on the .es syntax, see Entity Source (ES) Syntax. Here is a minimum compileable source for the Blob class:

1001
%{
#include "StdH.h"
%}

class CBlob: CMovableModelEntity {
name "Blob";
thumbnail "";
properties:
components:
functions:
procedures:
Main() { }
};

The number on the top is the identifier of the class. Without explanation, 1001 is chosen arbitrarily now. Below the identifier, there is an initial C++ code block, and header file for precompiled headers is added there.

Finally the Blob class is declared with no thumbnail, no features, no components, no functions and just an empty Main() procedure.

Adding the C++ Sources to the Project

When you have added the above snippet to the source, build the project. The build should succeed, but there is still no code. The first build has just created the C++ source files from your entity source.

Following files were created:

	Blob.cpp
Blob.h
Blob_tables.h

Now add those files to the project, and build it again. This build has really compiled the created C++ file Blob.cpp.

IMPORTANT: Since those three files are auto-generated from 'Blob.es', you must never edit them manually, because any of your changes would be lost with the first next recompilation of 'Blob.es'. Also, if you use SourceSafe, or any other source control system, you must never add the autogenerated files to the source control, because that would make them read-only. Those files are intermediate files, just like '.obj' files, and it is enough to add '.es' to source control. The rest can be rebuilt from it.

Creating the Entity Link

The class is now compiled and exists inside the 'Tutorial.dll' package. To be able to insert it in a world using Serious Editor, you must have an Entity Class Link (.ecl) file for it.

In the 'Classes\' directory in engine dir, create a text file (using NotePad, or similar) named 'Blob.ecl'.

NOTE: This 'Classes\' directory is in the engine dir, that is where the game and sdk are installed. It is not the Engine\Classes directory in the sources directory. If you have not yet unzipped the .gro file, you probably do not have Classes directory in the engine dir. Either unzip the .gro file, or create the directory manually.

Edit the file to look like this:

Package: TFNM Bin\Tutorial.dll
Class: CBlob

Make sure that you have pressed 'enter' at the end of the last line.

This file represents the class in SeriousEditor, and the class is added to a world by dragging the .ecl file and dropping it onto the world.

Adding Required Features for a Usable Class

This class now exists and has its link file. Before you can drag-and-drop it to a world in SeriousEditor you must add some more code to it.

It must have a thumbnail. Edit the line with thumbnail definition and enter "Help\\SDK\\Models\\Blob\\Blob.tbn" instead of the empty string. This thumbnail is just a texture file (same as .tex, just that this one has .tbn extension), and it is used when the SeriousEditor displays the classes in the VirtualTree Browser window, or in file open dialog preview.

It must have some appearance. We will use a pre-created model for this tutorial. First add the model and its texture as components by typing this under the 'components' keyword:

  1 model   MODEL_BLOB     "Help\\SDK\\Models\\Blob\\Blob.mdl",
2 texture TEXTURE_BLOB "Help\\SDK\\Models\\Blob\\Blob.tex",

Now, add this code to the Main() procedure:

    InitAsModel();
SetPhysicsFlags(0);
SetCollisionFlags(0);

// set appearance
SetModel(MODEL_BLOB);
SetModelMainTexture(TEXTURE_BLOB);
return;

This tells the engine that this class should be rendered as a model, sets its physical parameters and chooses the model and the texture. These physical parameters will just make it float in the air with no interaction with the other entities in the world.

Testing the Class in SeriousEditor

Now build the project and run it from the debugger. If you do not have the debug build of the editor, you will have to build and run the release version.

SeriousEditor will start. For info on how to work in the SeriousEditor, see its accompanying documentation. You should now load a test world from the 'Help\SDK\Worlds\Room.wld'. It is just an empty room with one light. Drop the 'Blob.ecl' in it, either using the Virtual Directory Browser, or directly from the Windows Explorer. A big green Blob should appear. Save the world as 'Blob.wld'

Adjusting the Model's Appearance

Now the little blob is in the world, but it does not really look the way it should. First of all it is not that little. The blob is 10 meters big. But it is not a problem, you can adjust its size dynamically. Add the following line before the SetModel() call:

	GetModelObject()->StretchModel(FLOAT3D(0.1f,0.1f,0.1f));

This should shrink the model 10 times.

Try that again in SeriousEditor. Make sure you exit SeriousEditor, build the project and run it again. (Though this looks like a tedious process if you have to repeat it a lot, it shouldn't be a problem, because SeriousEditor starts in a matter of seconds.)

Now the model is of a moderate size, it comes to just under your waist. Exit the SeriousEditor and continue to adjust the code. If you want to check it out in the SeriousEditor once in a while during the process, feel free to do so whenever you want.

The next thing you can notice (if you have checked the Blob model in SeriousModeler) is that it should be a kind of shiny, while the one in the world is diffuse. To make it appear same as in modeler, we have to add specular and reflection textures to it.

Start SeriousModeler and load the Blob model from the 'Help\SDK\Models\Blob\' directory. Press 'Q' to invoke the info window and select 'Global' tab. There you can read which specular and reflection textures the model uses. To add those textures to the Blob class, add the following components:

	10 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex",
11 texture TEX_REFL_LIGHTBLUEMETAL01 "Models\\ReflectionTextures\\LightBlueMetal01.tex",

and add code that will set those to the model after SetModelMainTexture() call:

    GetModelObject()->mo_toSpecular.SetData(
GetTextureDataForComponent(TEX_SPEC_MEDIUM));
GetModelObject()->mo_toReflection.SetData(
GetTextureDataForComponent(TEX_REFL_LIGHTBLUEMETAL01));

Now the Blob should be shiny.

Making It Move

But the blob just levitates in the air wherever you put it. To start the blob moving, you must adjust its physical parameters.

First change the calls to SetPhysicsFlags() and SetCollisionFlags() to this:

    SetPhysicsFlags(EPF_MODEL_WALKING);
SetCollisionFlags(ECF_MODEL);

That marks the Blob as a model which behaves like a live being. This is a usual setting for models like enemies, or player. The constants used here do not originate directly from Serious Engine, but are Serious Sam dependent. Collision flags are defineable by application. For short, you must include one more file below 'StdH.h', or in the StdH.h itself:

	#include <Entities/Common/Flags.h>

This file defines all the collision and physics flags used by SeriousSam entities. When you use it, you make your entity compatibile with SeriousSam entities for collision.

Also, you must jump-start the physics functions for the Blob. You do that by adding the following line at the end of the Main() procedure:

	// initialize moving
SetDesiredTranslation(FLOAT3D(0,0,0));

If you test it now, you can see that the Blob has fallen to the floor as soon as the game was started (it can be positioned in the air in the editor because time is frozen while editing). Also, you cannot pass through it anymore, because its collision works now.

To make it really move, change the last line to this:

	SetDesiredTranslation(FLOAT3D(0,0,-1));

That makes the Blob move forward at the speed of 1 meter per second.

Adding Some Will

The blob now moves, but when it hits a wall, it stops. It is actually trying to move, because its desired translation is still set to (0,0,-1), but the collision with the wall prevents it to move.

To make the blob behave more reasonable, you must add some kind of primitive 'AI' to it. It will not really be AI, just some basic behaviour.

Let's say you want the Blob to bounce up and down. It should jump up, wait while it flies, then when it hits the ground, it should wait for a bit as if preparing for the next jump and repeat the process.

To do that, instead of the last line write the following code:

    // repeat forever
while(TRUE) {
// pulse jump up
SetDesiredTranslation(FLOAT3D(0,10,0));
autowait(0.1f);
SetDesiredTranslation(FLOAT3D(0,0,0));

// wait
wait() {
// if touched something
on (ETouch) : {
// stop waiting
stop;
}
// ignore all other events
otherwise() : { resume; }
}

// wait a bit on impact
autowait(0.5f);
}

This translates the description of the wanted behavior to the entity source code.

If you try that, you will see that it really does behave as described.

The Animations

Ok, the Blob is jumping up and down, but it looks a bit too stiff for a piece of jelly. It should show some effect on each impact with the floor.

It can be accomplished by playing the 'Melt' animation of the Blob model. You can view it in modeler. In the animation, the Blob hits the ground, compresses, then it decompresses again as if bouncing. That is just appropriate. To be able to play the animations, you must know their names. Take a look at the 'Blob.h' file in the same directory as 'Blob.mdl'. That header file is autogenerated by the SeriousModeler each time the model is saved. It contains the following two lines defining the animations:

#define BLOB_ANIM_DEFAULT_ANIMATION 0
#define BLOB_ANIM_MELT 1

First, include the '.h' file at the top cpp block.

	#include <Help/SDK/Models/Blob/Blob.h>

Now to play the animations, replace the following block:

      // wait a bit on impact
autowait(0.5f);

with this one:

	// play the bouncing animation
GetModelObject()->PlayAnim(BLOB_ANIM_MELT, 0);
// wait for the bouncing to finish
autowait(GetModelObject()->GetCurrentAnimLength());
// continue in still pose
GetModelObject()->PlayAnim(BLOB_ANIM_DEFAULT_ANIMATION, 0);

Try that one out to see what it looks like.

Conclusion

If you did all that, the final file should look like the supplied Blob.es. This is just a basic tutorial. Take a look at the entity documentation for more deeper insight to entity source syntax.