Site hosted by Angelfire.com: Build your free website today!
Previous Page
Next Page
Table of Contents


Communication between objects

Objects can communicate with each other just fine by updating each other's data, in theory. It is a much better system, however, to allow for event-driven logic to guide programming in addition to general-purpose procedural programming. A number of messages can be initiated, either by sprite collisions or other objects, to directly affect the course of objects.

What happens when messages are sent

The object that sends the message fires off information to one or more other objects. The program flow of the sender is unaffected. If the sender used an "order" command to send the message, the sender just continues to execute more commands. If the sender and receiver are the same object, the object won't jump to the message label specified.

What happens when messages are received

The object that receives the message jumps to the appropriate message-related label. If the receiver does not have the correct label, the message is ignored. If the receiver does have it, the resume information is set to the previous object script location, and hobj (if present) becomes a pointer to the sender.

When the receiver gets its turn to execute its object script, a variety of things may occur. The receiver, which had jumped to the label location in the script, may choose to continue at this new script location or abort the location. If continuation is picked, the resume information is set to invalid at the end of the object's turn. If not, the "resume" command is executed. This statement tells the command interpreter to forget the message and proceed where it left off before the message, reseting the resume information in the process.

The advantage of this system is that an object can test the message for significance, usually by checking the object type that generated the message. If it is deemed insignificant, the message can be ignored even after it is generated.

Tertiary relationships

A message from one object to another accomplishes only one type of interaction: a two-object interaction. Binary communication systems obviously fall short of three-object, four-object, or more-object interactions. If two or more objects try to send a message to a destination object at the same time, there can only be one piece of "origin" information deposited in hobj at the time of the message.

A few options are open to solve a problem like this. One way to do it is to synchronize objects so that tertiary interactions never occur. Seeing how difficult this is, it is also a solution to log every sender of a message with the idea of processing information from all objects that tried to communicate with the receiver. This requires a lot of memory and time, unfortunately, plus the added uncertainty of how literally every type of tertiary reaction would pan out.

My solution is simple, even if not always satisfactory. The message control block tells what order to evaluate the messages. For example, a hit message is most likely to happen continuously if it is ignored for just the first 1/60th of a second the collision occurs. Other messages, such as triggered, will happen only a single time and cause a big disturbance if they are ignored. The most significant message evaluates first, the next significant message evaluates next, all the way down to the least significant one, which has the least precedence. Some messages will indeed be ignored, but their relative importance determines the physics of the game.

Tertiary interactions can be important when dealing with games that involve things such as rapid-fire damage, where it makes a significant difference how much damage an object takes whether or not multiple hits per frame cause a summed amount of damage. Nibbler is not a game that insists on such "summing" demands; it is geared toward binary interactions and discrete puzzle solutions.

Simple messaging: "order" command

To order an object to jump to a message label, write this:

order anobjptr, alabel;

Object pointers are self-explanatory, but "alabel" must be declared in the inter-object message control block. It is not possible to send any "custom" message label to the receiving object. For that matter, it is not really necessary--the same object pointer may be used to set a variable in the receiving object that can be interpreted as additional communication information. For example, a snake can find out what hit it instantly by inspecting its "deathmethod" variable, which is often set by objects that are coded to use specific pointers to index a snake object's local variables.

Any label other than a "hit" label (which can also be sent using an order command) will trump a "hit" label. In other words, two messages sent to the same object, one "hit", one not, will result in the non-"hit" label being transferred.

Collision messaging

The "hit" label is the target label whenever a sprite collision occurs. A "move", "moveoff", or "moveobj" command by either the sender or the receiver generates the message in both objects, provided the label is available to jump to. A change of sprite or the creation of an object will not initiate a "hit" label.

Collision logic works by the following steps:

1) Check the two objects' block flags.
2) If one is clear, forget it. If both are set, proceed.
3) Check the rectangular boundaries of the sprites, doing a subtraction on the center points and the sprite dimensions.
4) If the sprites are outside of each other, forget it. If touching each other (overlapping, even by the slightest pixel), proceed.
5) Consult the priority table. Read the current object as the row and the destination object as the column.
6) Get a numerical value. If another object has generated a "hit" message, compare the priority table entry of that object to the one that was just checked. The greatest numerical value in the priority table is the object whose message "wins."

In some ways, the priority table does act on tertiary interactions. However, it still obeys my "most important message takes all" algorithm rather than a summing data process algorithm. Priority table entries cannot be changed on the fly, but must be preset when it comes time to compile the script.

More about the priority table

Somewhere in the object scripts is a directive #ptable "file", which defines the priority table in text format. The text table is actually a spreadsheet that is saved in an easily compiled format. It took a LONG TIME to create the priority table. This is one tedium of creating a game with so many interacting physics--the physics have to be divided into various levels of significance.

Each table entry has two possible attributes: a number from zero to 63. The number defines the precedence of the object-object message interaction, the higher numbers being the more significant. All these values are weighed relative to each other on the same row--they don't have actual significance on a larger scale. A value of zero says that particular object-object interaction will be ignored, which is useful for cutting down on excessive object recognition logic.

The #ptable directive must be placed strategically. All objects capable of sprite collision logic must appear after the directive. All objects that will not use the logic (have block flag=clear always) should appear before the directive. The same order and number for the priority table and the "hitscannable" objects must be observed.

Other means of communication

Objects still have to interpret numbers and run routines; labels are just one way to pass along information. Labels are more commonly used for looping and general controls in the confines of a single object script. An object usually declares various local variables to be used as counters and fields to be updated for other objects and sometimes by other objects. Ultimately, the programmer must know how the objects will interface with each other before deciding which object will get what label at what time.



Previous Page
Next Page
Table of Contents
Back to Title Page