PROGRAMMING BASICS (for C++ users only) Open your compiler and visualize the code in the 3impactDLL.cpp file. Follow this tutorial to know how to do so. If you have never programmed before, consider the lines of text on your screen as the steps of a recipe. The engine will read each line of code from the top to the bottom, and will perform the action specified by each line. In some cases, it will execute a sequence of lines again and again, in a loop. It can also execute sections of the code only if certain conditions are met. Read this document for an overview of what the engine does with the 3impactDLL.cpp code (DLL code). Note that text lines preceded by // are comments, not code lines. They are completely invisible to the engine. They are only meant to provide the human reader additional information about the code. Also note that each code line must terminate with a semicolon (;). Forgetting to do so when writing your own code is a very common mistake. The only quick way to understand the DLL code is to try modifying it a little bit and then compile and run the DLL to see what the engine does. This document provides some basic concepts that will help you understand how the DLL code works in general and learn how to write your own. INCLUDES The code starts with some include lines like #include #include #include #include
<windows.h> <stdio.h> <math.h> "..\common\3impactDLL_defs.h"
Include lines are not lines of code. Instead they specify additional files that include lines of code written by others. Such external code allows you to call specific functions in your custom DLL code. For example, you can call the function named iCameraCreate() because you have included the 3impactDLL_defs.h external file. Includes are used to enable access to common C functions, Windows interfaces, 3Impact-specific functions and even custom written function libraries and DirectX® functions not directly supported by the engine. VARIABLE DEFINITION The second section of the DLL code is a sequence of variable definitions, like CAMERA* Camera; SPRITE* LoadingMessage; SKYBOX* SkyBox; BODY* Terrain;
MESH* TerrainMesh; BODY* Ball; MESH* BallMesh; MESH* BallMeshShadow; BODYBODY* BallTerrain; Each line defines a variable. Each definition is made of a type specifier, like for example MESH*, followed by a custom name, for example BallMesh. Defining a variable means assigning a type and a name to a small portion of system memory (Ram). For example float MyValue; gives the name MyValue to a block (4 bytes) of memory, and assigns the type float to it. It basically means that when the engine executes a line of code like MyValue = 17.379f; the value 17.379 is put into the memory associated with MyValue. Note that the f at the end of the value is needed. It tells the compiler that the constant value specified is a floating point number. Because MyValue is of type float, you can only put floating point numbers in it. Variables of specific types can store specific types of data only. For example CAMERA* MyCamera; defines a variable named MyCamera that can only be used to store a camera object, as returned by iCameraCreate() function. For example MyCamera = iCameraCreate(0,0,100,100); VARIABLE TYPES The primary variable types you will use in your DLL code are object variables. Object variable types include CAMERA*, SKYBOX*, BODY*, MESH*, etc. They are used to store the handles of created objects (cameras, meshes, etc), so that they can be passed as parameters, elsewhere in your code, to object-manipulation functions, like for example iCameraLocationSet(). Another very common type of variable is float (see above). It is used to store values and can be used in expressions, like ValueA = (ValueB + 2.3f) * ValueC; The D3DXVECTOR3 type is very common too. It is used to store a set of 3 floats so that they can be efficiently manipulated as if they were one single variable. This type is used to store vectors. Each single element of a vector variable can be accessed by using a special syntax, which wants the variable name, followed by a dot, followed by x, y, or z. For example D3DXVECTOR3 MyVector; MyVector.x = 1.4f;
MyVector.y = 0.0f; MyVector.z = 2.0f; The D3DXQUATERNION type is similar, but it is made of a set of 4 floats. It is used to store 3d object orientations. ARRAYS You can define any number of variables of the same type with one single definition. For example, you can define a list (array) of 100 variables of type float as follows: float MyValue[100]; where MyValue is the name of the array. You can access each variable in the array with something like MyValue[76] = 11.371f; Note that the first variable of the array is MyValue[0] and that the last one, in this case, is MyValue[99]. Accessing (e.g. trying to put a value into) variables past the last one defined produces strange bugs that are hard to find and fix, and is a very common mistake. Other valid array definitions are D3DXVECTOR3 MyVector[120]; MESH* MyMesh[20]; VARIABLE SCOPE Defined variables can only be used in the lines of code that follow the definition. Trying to use a variable in the lines that precede the definition, will result in an 'undefined variable' error message, when the DLL code is compiled. Variables defined inside a {...} section, like for example inside a callback function as follows void Run() { float temp; ... } cannot be used outside that section. It means, for example, that the temp variable defined above is not available (not defined) in the Init() {...} section. Note, however, that the temp variable IS defined in any nested {...} section within the Run() {...} section. For example void Run() { float temp; temp = Timer + 3.5f; if (temp > 10.0f) {
temp = 0.0f;
}
} ...
the temp variable CAN be used in the if() {...} section. EXECUTABLE CODE Executable DLL code is inside the {...} big sections of the callback functions only. You cannot write executable code outside callback functions' {...} sections. Only include lines and variable definitions can live outside all {...} sections. FUNCTION CALLS The executable code is basically made of just variable expressions and function calls. They are commands for the engine like create a mesh, place it there, apply this force to it, and so on. You can recognize a function call because it is a custom name followed by round parentheses. For example iMeshShow(BallMesh); The parentheses can enclose one or more parameters, separated by commas, or no parameters at all. Each function wants a specific list of variables (or constants) as parameters. For example, iParticleAirResistanceSet() wants a PARTICLE* variable as first parameter and a float variable as second parameter. So a typical function call for it will look like iParticleAirResistanceSet(Fire,ResistFactor); where Fire was defined with PARTICLE* Fire; and ResistFactor was defined with float ResistFactor; Or it can look like iParticleAirResistanceSet(Fire,0.75f); Where 0.75f is a constant data of type float. Function parameters can also be expressions, like iParticleAirResistanceSet(Fire,(Base+User)*0.5f); The engine will compute the (Base+User)*0.5f expression and will pass the result to the function as a parameter. The name for all 3Impact-specific function calls starts with a lower-case i. All 3Impact functions
are described in the Reference document. NOTE: void PreInit(), void Init(), void Run(), void Exit() and void PostExit() are not function calls. Instead they are [callback] function definitions because they appear outside all {...} sections. They are actually formed by the void XXX() line and the whole {...} section that follows it. THE "IF" STATEMENT You can have a piece of code executed only if a certain condition is met by using the if statement. For example if (temp == 10.0f) { //this {...} section is only executed //when 'temp' contains 10.0f } where the parentheses following the if statement enclose an expression and the {...} section below the if statement line encloses the piece of code to be executed if the expression is TRUE. The if statement can also be used as follows: if (temp == 10.0f) { //this {...} section is only executed //when 'temp' contains 10.0f } else { //this {...} section is only executed //when 'temp' does NOT contain 10.0f } NOTE: two == are used to compare. For example to compare the variable named temp with 10.0f. The whole thing constitutes an expression that can be TRUE or FALSE. Instead, one single = is used to put something into a variable. Confusing the two concepts is a common mistake which causes bugs that may be difficult to understand and fix. THE "WHILE" STATEMENT You can have a piece of code executed again and again until a certain condition is met by using the while statement. For example temp = 0.0f; while (temp < 10.0f) { ... temp = temp + 1.0f; } where the parentheses following the while statement enclose an expression and the {...} section below the while statement line encloses the piece of code to be executed again and again while the expression is TRUE.
In the example above, the {...} section is executed 10 times, because at every execution the temp variable is increased by 1, thus failing to be less than 10 after ten loops (the expression becomes FALSE). THE "FOR" STATEMENT You can have a piece of code executed a specified number of times by using the for statement. For example for (int i=0;i<10;i++) { ... } will execute 10 times the lines of code within the the {...} section below the for statement. There is much more to know about C statements. Try seeking the Web for keywords like 'C language for statement' or 'C language switch statement'. REMARKS The DLL code is ANSI C++. It means that you can use ALL the power provided by C++ syntax when coding your DLL! Still, with 3Impact, you don't have to understand all that complex stuff coming with typical C++ code. The simple information provided in this document and a little bit of practice should be all you need to write your own DLL! Don't hesitate to seek for help at the forum if you need it. Keep in mind that ALL the guys and gals at the forum were beginners once!