Skip to content

2. The Object Controller

Triangly edited this page Oct 17, 2024 · 4 revisions

While c_framework serves as the main controller of the framework, another important component is the c_object controller.

In object-oriented programming terms, c_object functions as a class for objects. Any object that needs to be managed by the framework must inherit from this object/class.

Similar to c_framework, c_object contains several component structures, but they do not perform any specific task by themselves:

  • Animation
  • Culling
  • Interact
  • Solid

The controller operates within the following events:

  • Create
  • Clean Up
  • End Step
  • Draw

In the Create Event, the aforementioned structures are initialised.
In the Clean Up Event, these structures are removed.
In the End Step Event, the presence of the parent object in the room is checked.
In the Draw Event, the object is drawn at a floored position.

If you need to override these events in an object that inherits from this controller, you must call event_inherited() function. Ignoring to do so will, in most cases, result in a game crash.

Animation

Structure:

data_ani

Available Fields:

none

Related Functions:

ani_get_duration() ani_get_ended() ani_get_frame() ani_get_frame_change() ani_get_stopped() ani_get_timer() ani_resume() ani_start() ani_stop() ani_run_by_timer() ani_update() ani_update_duration() ani_uodate_frame() ani_update_loopframe() ani_update_order() ani_run_by_frame()


The Animation component is highly sensitive to changes, so it does not have any accessible fields, and any interaction with it should be done exclusively through dedicated functions. It's important to note that the object itself does not update the variables within this structure. Instead, c_framework handles these updates during the Begin Step Event.

As a result, all animation updates occur at the start of the frame, before any objects are updated.

Culling

Structure:

data_culling

Available Fields:

  • behaviour - the current culling type
  • parent_object - the parent object (noone if doesn't exist nor set)

Related Functions:

obj_set_culling()


Culling in Orbinaut functions similarly to how it works in the original engine: c_framework loads objects within a specific radius of the camera's position, and the objects themselves check whether they are outside these bounds. Depending on their culling type, they may pause, reset, or continue their operation. The culling type also determines the object's behaviour when the framework is paused.

  • CULLING.NONE: No culling is applied. The object is not processed by the system and remains always active (unless you deactivate it manually), regardless of any circumstances.
  • CULLING.PAUSEONLY: The object is deactivated only and only when the framework is paused (i.e., when c_framework.state equals STATE_PAUSED). So, if c_framework.state equals, for example, STATE_STOP_OBJECTS, the object will not be deactivated.

The following culling types are only applied when the framework is in the active state (c_framework.state == STATE_NORMAL), otherwise the object is deactivated:

  • CULLING.ACTIVE: The object is unaffected by the camera's culling boundaries and will remain active even at the far end of the room.
  • CULLING.REMOVE: The object is removed from the room as soon as it goes outside the active area.
  • CULLING.DISABLE: The object is deactivated once its current position leaves the active area.
  • CULLING.ORIGINDISABLE: Similar to CULLING.DISABLE, but it checks the object's starting position.
  • CULLING.RESPAWN: When the object's current position goes outside the active area, it respawns: its initial parameters are restored, it returns to its initial position, the Create Event is executed, and then the object is disabled until it is activated by the camera.
  • CULLING.ORIGINRESPAWN: Similar to CULLING.RESPAWN, but it checks the object's starting position.

As mentioned above, for the CULLING.RESPAWN and CULLING.ORIGINRESPAWN types, the Create Event is executed again when the object respawns. This means that if you create any child objects created there, you must ensure they are deleted to prevent duplicates. You can use the parent argument of the framework's instance_create() function in this case, as the game will handle the deletion of dependent objects automatically.

Parent object can be accessed via the data_culling.parent_object field, and the culling type can be determined through data_culling.behaviour.

Important: by default, the culling type is set to CULLING.ACTIVE.

Interact

Structure:

data_interact

Available Fields:

  • interact - Indicates whether the object's hitboxes are active or not.
  • radius_x - Horizontal radius of the primary hitbox.
  • radius_y - Vertical radius of the primary hitbox.
  • radius_x_ext - Horizontal radius of the secondary (extra) hitbox.
  • radius_y_ext - Vertical radius of the secondary (extra) hitbox.
  • offset_x - Horizontal offset of the primary hitbox.
  • offset_y - Vertical offset of the primary hitbox.
  • offset_x_ext - Horizontal offset of the secondary hitbox.
  • offset_y_ext - Vertical offset of the secondary hitbox.

Related Functions:

obj_set_hitbox() obj_set_hitbox_ext() obj_check_hitbox()


The Interact component manages the object's interactions with other objects through their hitboxes. Each object has two hitboxes: a primary and a secondary (extra) one. The hitboxes are centered on the object, and their offsets can be adjusted using the appropriate function arguments.

An object can interact with one other object per frame. After this interaction, the data_interact.interact flag is set to false until the start of the next frame.

Solid

Structure:

data_solid

Available Fields:

  • no_balance - Determines whether the player should balance on this object or not.
  • radius_x - Horizontal radius of the solidbox.
  • radius_y - Vertical radius of the solidbox.
  • offset_x - Horizontal offset of the solidbox.
  • offset_y - Vertical offset of the solidbox.

Related Functions:

obj_set_solid() obj_set_solid_sloped() obj_check_solid() obj_act_solid() obj_clear_player_push()


Solid collision is targeted towards the player and isn't really a universal component. It works based on the collision algorithm from the original Sonic engine, which might not be optimal for games of different styles or genres. If that's the case, this component and its dependent functions can be removed.

Similar to hitboxes, the solidbox is centered on the object and can be offset.

Collision with the player is managed through the obj_act_solid() function. This function handles player landing, movement on the object, and movement with the object itself. It should only be called after the object has updated its position to avoid visual or other issues.

Solidity for an object is defined using an enum passed as the type argument in the aforementioned function. Here are the available solidity types:

  • SOLIDOBJECT.FULL - The object is solid on all sides.
  • SOLIDOBJECT.TOP - The object is solid only on the top.
  • SOLIDOBJECT.SIDES - The object is solid only on the sides.
  • SOLIDOBJECT.ITEMBOX - Special solidity rules apply for obj_itembox.

It’s important to note that if the player is standing on an object and the obj_act_solid() function stops executing, the player will still be considered standing on the object, which causes the Slope Glitch. In such cases, you’ll need to manually reset the player’s is_grounded and on_object states by doing the following:

player.on_object = noone;
player.is_grounded = false;