Game Objects
E02 supports up to 4096 simultaneous Game Objects. Game Objects are enemies, obstacles, items, projectiles, etc. that populate a Level.
There are some very important Built-in Object types for menus, displays, overlays, and even for activating and displaying Player Characters and Tile Planes, but any game-specific entity types must be created by script using the following system:
Object Def
Object Variables
Object Management
Object Spawning
Object Destruction
Object Saving
Activity Range
Resetting Objects
Object "Fetchinging", Pointers, and Relationship
Projectile Objects
Objects as "Players"
Solid Objects
Tiled Path Objects
Object Def
The Object Def is a setup file used to define the properties of any Game Object Types to be used in any particular part of a game. The Game Def loads one of these files for game-global Objects. Each Zone Def can load a file for Objects belonging specifically to that "Zone", and can also load files corresponding only with each "Act".
Object Variables
The Object Variables are settings that are read and modified during gameplay by E02 and Script Functions to determine or control where the Object is and what it is doing.
Object Management
Object Management consists of three normal gameplay phases and two placement phases, each of which is composed of a Hard-coded Function, and a Script Function:
- Movement Phase
The Movement Phase is processed first, and only once per Game Frame. At the beginning of this phase, Player Hard-coded Movement is processed for each Player Character, but only if that Character is associated with an existing Player Movement Object.
Next, all "active" Game Objects are processed for movement in order of Priority. First, the Built-in Object Movement Function that is specified for this Object's type in the Object Def is processed, and is immediately followed by the Object's currently-active Animations. Afterward, any active Scripted Movement Functions for this Object are processed.
The primary Scripted Movement Function, which is specified for each Object type in the Object Def, is only called once, when the Object is spawned. This means that the Function must break and loop in some way if it is meant to process again for each Game Frame that the Object is active.
This also means that the Function may begin with steps to initialize the Object, which should happen only on the first Game Frame on which the Object becomes active, if the Function is made to skip that section when it loops.
Multiple Scripted Movement Functions may be running for any Object, and may be managed at any time by calling any of the external Object Movement Function Control Script Commands.
After all previously-existing Objects have been processed for Movement, any newly-spawned Objects will be processed and then sorted among the others according to Priority.
- Collision Phase
- Drawing Phase
- Debug Drawing Phase
- Debug Placement Phase
Object Spawning
There are two methods for spawning Objects:
- Debug Placement
Debug Placement is only useful for the initial construction of a Level's Object Layout. Any settings applied by the Scripted Debug Placement Function are included in the generated "Resetted State"
- Func_SpawnObject
Upon Spawn, the Object's standard variables are set according to the method with which it was spawned, and its "Extra Variables"
are initialized according to its "Spawn Values", as defined in the Object Def.
Immediately after that, the Scripted Object Move and Draw Functions that are specified for the Object's Type in the Object Def are added for processing. This is the only time that this occurs, so if these functions are meant to be recurring throughout the Object's life, they must break and loop.
Newly-spawned Objects are processed for Movement after all pre-existing Objects, and then sorted according to Priority at the end of the Movement Phase.
The last Object that was Spawned can be "Fetched" for access by using the Func_FetchObject_Last_Spawned Script Command. If the Object was Spawned using Debug Placement, it is considered to be the "Current Object" during processing of the Scripted Debug Placement Function.
Object Destruction
Objects are "destroyed" by having their Object_Type variable set to 0.
This can be done manually, or by use of the Func_Destroy_Current_Object Script Command.
Either method is safe to use at any time.
Objects may also be flagged to be destroyed automatically when they exit Activity Range.
When an Object that has been "destroyed" is encountered during the Movement Phase, all resources used by that Object are immediately freed, and so any references to that Object become invalid. Any attempt to access the Object after this point will result in undesired behavior and/or crashes, so when a destructible Object is manipulated by Script Functions not belonging to that Object, it is important to be prepared for this case.
Object Saving
Activity Range
"Activity Range" is defined as anything within the 320x224 pixel-unit area that makes up either active display screen, and up to 160 pixel-units away from any of their four borders. If Split-Screen mode isn't active, this only applies to the one visible screen.
Objects are within "Activity Range" when their exact X/Y Position is within these boundaries. These Objects are always processed for Movement, Drawing, and Collision.
Objects outside of this area are governed by their Type's "Out of Range Event", specified in the Object Def, in this manner:
- 0 - The Object remains frozen in place in its current state; it is not processed in any way.
- 1 - The Object remains "active"; it continues processing as if it were within "Activity Range"
- 2 - The Object is reverted to its "Reset State" as soon as that state and its active state are both outside of "Activity Range". Until then, it is made inaccessible and held in suspension.
- 3 - The Object is destroyed.
- f - "f" prefix for a value (such as "f10", "fZ1") references a Scripted Object Movement Function to run once, when the Object first falls outside of "Activity Range". Otherwise behaves like "0".
- F - "F" prefix for a value (such as "F13", "FA2") references a Scripted Object Movement Function to run once, when the Object first falls outside of "Activity Range". Otherwise behaves like "1".
If a Function is used, it is called when a previously-active Object that now falls outside of "Activity Range" is first met during the Movement Phase. If the Function breaks and/or loops, it will be treated as a normal Scripted Movement Function, and will continue processing each time the Movement Phase occurs when the Object is again considered to be "active", until it either ends or is disabled.
Resetting Objects
Object Resetting is one of the Object Def "Out of Range Event" settings for an Object Type, which causes the Object to return to its "Resetted State" when it falls outside of "Activity Range". If, however, its Resetted State still falls within that range, the Object will be rendered completely inaccessible until it can be Reset without immediately becoming "Active" again.
This effectively returns Objects to the states in which they were placed once the Player leaves and reenters the area, and is used for resetting enemies, restoring Objects such as collapsing platforms and movable gimmicks that are necessary for progression within the level, etc.
An Object's "Resetted State" is created when the Object is spawned, but can be modified by using the Object Editor option to store the current state of a modified Object.
Objects that have been "destroyed" are gone for good, and cannot be reset. If an Object is to appear to be "destroyed", but then reset when the player leaves and reenters the area, it must instead be made invisible and otherwise undetectable.
This can be accomplished by switching to an Animation or Sprite Set that "displays" invisible Sprites and temporarily ignoring collision, by moving the Object outside of the gameplay area, or by switching the Object's Type setting to a type that is flagged to Reset, but has no drawing, movement, or collision settings.
The Func_Stop_???_Object will immediately stop all of an Object's Functions and Animations, and change its Type setting.
Object Resetting can't manage Object Relationship, so Objects that must Reset and must also manage Children should not have those Children spawned and attached by the Scripted Debug Placement Function. This should instead be handled by an "init" section at the beginning of their Scripted Movement Function, before its main loop, so that they are re-spawned immediately after every reset.
All Objects whose Type are set for Resetting are automatically Reset when Object Layout is saved, and when entering the Object Editor while not holding the "Alt" key.
Object "Fetching", Pointers, and Relationship
Object "Fetching" is the method by which Objects are set as the "Source" and/or "Destination" for Script Commands that manipulate Object Variables, or any other aspect of an Object. Because there are at most two Sources and one Destination used by any Script Command, there are three "References" that any Object can be "Fetched" into. Using the mathematical add operation as an example, the general rule is:
Z = X + Y
Where:
- X is Reference 0 - The first Source operand
- Y is Reference 1 - The second Source operand
- Z is Reference 2 - The Destination operand
This is also true for operations with only one Source operand, and for non-mathematical operations.
Any Object that is being manipulated in any way is considered to be the "Destination", while any Object or Player that provides information for the manipulation of the Destination is considered to be a "Source".
If a Command uses only one Source, The one Source Parameter is "Reference 0".
If there are two Sources that are both Objects, then the first Source Parameter is "Reference 0", and the second is "Reference 1".
Since Players are considered distinct from other Objects, they have their own set of References; this means that if there are two Sources, one Object and one Player, the first Source Parameter is "Reference 0" in terms of Objects, and the second Source Parameter is "Reference 0" in terms of Players.
A single Object may be "Fetched" to more than one "Reference" if it must serve as both Sources, one Source and the Destination, or both Sources and the Destination.
Pointers to Objects can be obtained by use of the Func_???_Equ_Pointer_???Obj_??? Script Commands and stored in any Object Variable, Game Variable, or Player Variable for later retrieval by "Fetch".
This method of Object referencing can allow any part of the game to keep up with any Object, but because the pointer is stored in a Variable, it cannot be identified as a pointer without explicit use of a pointer-manipulating Script Command, and therefore cannot be properly saved and re-loaded with Object Layout. There is also no way to determine whether or not a Pointer references an Object that has been destroyed, so this must be kept up with manually.
Object Relationship is another way of keeping track of existing Objects. Any Object may have one Object set as its "Parent", and any number of Objects set as "Children". This is handled by the Func_Set_???_Obj_Parent/Child Script Commands. Parent Objects can be set to automatically destroy their Children when they are destroyed themselves, and Object Relationship can be saved to Object Layout files.
Projectile Objects
"Projectile Objects" are Objects that use the "Projectile" versions of Built-in Movement Functions, which cause them to test for collision against other Objects.
As Projectile Objects move, they trigger the same "Collision Phase" as Players, once for every pixel-unit of motion, except that Built-in and Scripted "Projectile Collision Functions" are used, rather than "Collision Functions". These Functions are still assigned to the target Object's Type (within the Object Def), and not the Projectile Object's Type.
Each Object Type may only have one Scripted Projectile Collision Function. When there is more than one type of Projectile, the best way to cause a different reaction to each would be to use the "Switch" Script Commands with the Projectile's Object_Type Variable.
Objects as "Players"
Objects may be used in place of "Players" when the complexity of the Player Management system is unnecessary.
This method uses less storage (assuming the Object is not an extension of an existing Character Def Character), and will process faster.
It also allows for more than two simultaneous players, although there are still only two available display screens.
This method can be used in conjunction with the standard Player Management system for any reason, either in separate levels, or at the same time.
The Objects may also be made to display Sprites from any currently-loaded Character Def by making the appropriate reference in its Object Def File.
These Objects can be made to respond to user input by using the Func_If_KeyState Script Command during their Scripted Movement Function to manually test for keypresses.
This Command supports KeyMaps, so a different Map may be used to monitor different input keys for each player.
The Curr_Player Game Variable will need to be manually set equal to the Object's "Player ID" before the tests are performed to take advantage of the "Current Player" KeyMap functionality.
If the screen is meant to scroll with these Objects, the vp?r[?] Game Variables will need to be updated manually at the end of the Object's Scripted Movement Function.
These Objects will generally need to be set as "Projectile Objects" so that they can directly interact with other Objects in the level through standard Collision testing.
Solid Objects
"Solid Objects" are Objects that are made such that, in whole or in part, Players and/or Projectiles can't pass through them.
This is generally accomplished by using the Func_If_Player/Projectile_Touch_Object Script Commands in the Object's Scripted Collision Function to determine when one side of the MainBounds Collision Box of a Player/Projectile comes into contact with the opposite side of the MainBounds Box of the Solid Object.
When a Player comes into contact with a Solid Object, the Player_Cant_Go_??? Player Variable that corresponds with the side of the Player on which the collision took place should be set to a nonzero value to stop his motion in that direction.
It is preferable to set this value equal to a pointer to the Object by use of the Func_Chr_Equ_Pointer_Curr_Obj Script Command so that other parts of the game can determine if/when the Player is touching this particular Object.
For proper collision with Players (but not Projectiles) during movement, the Scripted Movement Function for the Object should use a ShovePlayer_Within_SolidObject_??? Script Command for each active Player when he is not already standing on the Object, and a ShovePlayer_???_Obj Script Command when he is.
This will cause the Player to move along with the Object if he is already standing on it, and to properly attach to or be pushed along by its MainBounds Box if he is not.
Projectiles that come into contact with the Solid Object must be stopped manually, in accordance with the way they were made to move.
If they are moved by one of the Built-in Object Movement Functions, this would be handled by setting the appropriate Object_?_Vel and Object_?_Accel variables ("Extra Variables" 2 and 5, or 3 and 6) to 0.
If the Solid Object can move, and must carry or push the Projectile, the Projectile's new position will need to be calculated and updated manually within the Solid Object's Scripted Object Movement Function.
Tiled Path Objects
"Path Objects" are Objects that use Level Tiles as their graphics, which Players (but not Projectiles) can react to as if they were a standard Tile Plane. Their main benefit is that, like any other Object, they can be made to move.
Path Objects are created by assigning the Object's Type a combination of Built-in "LevelTiled" Object Draw and Object Collision Functions.
When a Player collides with any solid portion of a Path Object, his appropriate Player_Cant_Go_??? Variables will automatically be set equal to a pointer to the Object by the Built-in "LevelTiled" Collision Function.
These Objects require the use of a "Plane ID" Variable, which functions similarly to a Tile Plane ID, in that a Player's Player_Solid_Plane Variable must be set equal to this value for him to test for collisions with this Object. This value may be equal to that of an existing Tile Plane (for example, when a Player must be able to collide with both the Object and the primary Level Collision Plane), or may be given a unique value that is not shared by an existing Plane (when the Player must be able to collide with the Object, but not the standard Level Layout).
For proper collision with Players during movement, the Scripted Movement Function for the Object must use a ShovePlayer_Within_TiledObject_??? Script Command for each active Player when he is not already standing on the Object, and a ShovePlayer_Riding_TiledObject_??? Script Command when he is. This will cause the Player to move along with the Object according to its Tile layout if he is already standing on it, and to properly attach to and begin following the Object if he is not.
Path Objects cannot normally be made to use the Built-in Movement Functions for mobile Objects that collide with the level because they don't use Sprites, and therefore, don't have "MainBounds" Collision Boxes. This can be overcome by associating Sprites and Animations with the Object which have the right boundaries set, but these Sprites won't be visible as the Object is already using the Built-in function for Tiled Drawing. In this case, it's also possible to use Scripted Collision Functions for the Object that alow Players and Projectiles to interact with the Collision Boxes defined for the invisible Sprites, as long as their shape, and the shape of the tiled area, allow those collisions to occur.