Patch:Galaxy Action Parameters
Galaxy action parameters are integral fields within Galaxy actions that control the movement of the objects (i.e., "sprites") or the action timing. The relevant subset of action fields is tabulated below. Note that the "Next action" field is a 2-byte (near) pointer to another action, but is included here anyway for completeness' sake. Remember that the game has (at optimum speed), 35 animation frames per second, corresponding to 70 game "tics" per second (thus, one frame completes in two tics). "Calling" a function means that the function code is executed in that animation frame.
Int Description Values Int 4: Action Type 0-4 Int 6: Deprotect Animation 0/1 Int 8: Stick to Ground 0/1 Int 10: Delay (Anim speed) 0-0x7FFF Int 12: H anim move amount +- any value Int 14: V anim move amount +- any value Int 30: Next action Valid actions
The action type defines how often the the behaviour function is called and how often the action movement amount offsets are applied. It takes five meaningful values (0-4) summarized below:
Movement Parm Behaviour Called... Action Movements Applied... Delay field is used? 0 Once Once Yes 1 Once Every frame Yes 2 Every frame Not applied No 3 Every frame Once Yes 4 Every frame Every frame Yes
The behaviour is called either once, right before the action changes to the next action, or on every animation frame. The action movements are applied to the object either once, when the action changes, or on every animation frame, scaled by the number of tics consumed by one animation frame (usually 2 tics/frame at optimum speed). The delay field is used, meaning it specifies the number of tics before the action is advanced to the next action, or it is unused, meaning the action repeats itself every frame.
In general, a behaviour that is called once would be used for spawning something (e.g., a slime puddle or projectile), while a behaviour called every frame would be used as a sensor. Movements applied once per action are used for jerky locomotion (pedal, or serpentine), whereas movements application every frame is used for smooth motion. Movement can also be defined in the behaviour, collision, and tile checking functions, in addition to the action movement parameters. Examples of where action parameters are found, and how they can be used are described below.
The bulk of sprites use type 0, meaning that the behavior is called AND the object is moved when action advances ( (i.e., when the sprite animates.) This is what makes poison slugs or arachnuts, for example, 'crawl' in jerks. If animation is often enough and speed slow enough, motion seems smooth.
Type 1 is similar to type 0, but movement is smoother. Here, the H/V movement offsets are applied every frame, depending on which way the berkeloid is facing. Berkeloids use this to make sure their 'floating' movement isn't jerky.
Type 2 actions ignore any movement and delay timers (animation speed). It is used notably for stunned falling sprites which keep falling all the time until they hit ground and move on. Airboards also use this. In other words, used for things that need to be instantly responsive. They won't animate and need movement defined in their behavior. Type 2 is best used for sensory behaviours. Type 2 actions are executed once, and only once, per animation frame.
Movement is jerky, happening every time the sprite animates. This is for things that need to be very responsive, but also animate. Dopefish and Mad Mushrooms use this because they must be able to react to walls and floors to avoid getting stuck. The behaviour function of these creatures defines the motion, which is why they do not move in jerks.
Type 4 is a rarely used case, sometimes used for things that are going to need to land on or leave the ground somehow. The flying bluebird does this for example, and it is about the only Keen 4 example.
The rarely-used, boolean "Deprotect Animation" parameter forces the action to run for the proper number of tics, even if this means skipping over an animation. If this flag is not set, the sprites for actions will be drawn for at least one animation frame, no matter how short the delay is (even a delay of 0 or 1 tics). If the flag is set, then these fleeting actions will still have their sprite behaviour function and movement parameters processed (but not the sprite collision nor tile-checking functions), but the animation MIGHT not be drawn (see the detailed explanation). This flag is most useful if you want to apply the action movement parameters or a behaviour instantaneously (using 0 for the delay), and you don't want the intermediate sprite to be seen, or you don't want a hiccup in the animation.
For example, you might want object A to call a single behaviour six times in a row by writing six sequential type 0 actions of delay 0. This behaviour might spawn object B at object A's location. If the animation is protected (flag = 0), then this will take a minimum of six animation frames, and object A will be drawn every frame. If the animation is deprotected (flag = 1), then all sprites will spawn on the same animation frame. In addition, the movement parameters can be tweaked so that object A is located at a different position for each object B spawn, and returns to its initial position after the sixth spawn. If animation is protected, then object A will skip around the screen, whereas if it is protected, its intermediate positions will not be drawn.
This parameter has no meaning for type 2 actions.
Detailed explanation: For any animation frame, when an action expires because it reaches its delay, the game runs the old action for a fraction of the frame length, and the new action for the remainder of the frame. As an example, assume that action 1 has 3 more tics to go, and the animation frame took 5 tics to complete. Then action 3 would be run for 3 tics and action 2 would be run for 2 tics. In the event that the second action is so short that there are still tics to be processed, the "Deprotect Animation" flag comes into use. If reset (zero), then the action is run for delay - 1 tics and no more actions are processed for that frame. If the "Deprotect Animation" flag is set (1), then the action is run for the specified number of tics and the 3rd action in the chain is processed for the remaining number of tics. Since the 3rd action is the last to be processed, its frame will be displayed, and the sprite frame for action 2 is never seen.
Stick to Ground
The boolean "Stick to Ground" (formerly, "Change V") parameter affects the vertical movement of the object. If Stick to Ground is 1, then the sprite will move DOWNWARDS by however far it moved left or right, for each animation frame. Some objects will malfunction if they leave the ground (e.g., inchworms and arachnuts). Because slopes are always less than 45 degrees, objects will always be forced into the ground if they are moving downhill. If an object is to walk along the ground, this flag should be set to 1. If the object is airborne, the flag must be set to 0.
Delay and Next Action
The "Delay" field specifies how many tics will pass before the action pointed to by the "Next action" pointer is selected. If an action has a delay of 70, that action will remain valid for one second until the next action is selected. Both fields serve no purpose for action type 2. For movement types 0, 1, and 3, the delay also regulates how often the behaviour function or the movement parameters are applied (see table above). If the next action is zero, then the sprite freezes.
H/V Movement Amount
The movement offsets allow for action-defined motion. Movement offsets (here, and in general) are always in 16ths of a pixel, or 256ths of a tile. Objects have an X-Motion (-1 = left, 0 = none, 1 = right), and a Y-motion parameter (-1 = up, 0 = none, 1 = down) that is defined by the sprite behaviour, collision, and tile-checking functions. For action types 0 and 3, the H and V values are applied when the action delay timer expires. For example, an action of parameter type 0, H-offset of 128, and delay of 35 will move right or left by a half tile every half second. For action types 1 and 4, the H and V values are applied every animation frame, and scaled by the number of tics consumed during that frame (approximately 2 tics/frame on DOSBox), meaning that the action delay is irrelevant for motion and that the motion is smooth. An object with action type 1 or 4 and a V-offset of 4 will move 1/4 (four 16ths) of a pixel every game tic, which is equal to 1/2 a pixel every game frame and about 17 pixels a second.
Movement can also be defined in the behaviour, collision, or tile-check functions. The offset applied in these functions is added to that defined by the action, and the net movement is applied to the object. Remember that, if the Stick-to-Ground flag is set, the vertical movement defined by either the action or a function is ignored.
Behaviour, Collision, and Tile Checking Functions
These are double-word pointers to the start of a function described in detail elsewhere. Note that the behaviour function is called every frame for action types 1,2, and 4, but it is called right when the action switches to the next action for types 0 and 3. The collision function is called every frame whenever an object is in contact with another object, and the tile-collion (draw function) is called every frame when the object is on screen.
Although not part of the "Id Engine" proper, the physics and action code is shared by many games that use the Keen:Galaxy engine. BioMenace, Dangerous Dave 3 and 4, and Rescue Rover 2 all use actions. Shadow Nights, Dave 2, and Rescue Rover 1 use the Keen Vorticons method of sprite control.