GameMaker CE - Collection of CC0 programming libraries

G

Guest

Guest
Pretty cool. 201 scripts for $2.01 would probably get the point across better. Not that you asked for my opinion.
 

kraifpatrik

(edited)
GameMaker Dev.
Pretty cool. 201 scripts for $2.01 would probably get the point across better. Not that you asked for my opinion.
Hehe, but the price is going to stay at $1.99 no matter how many more scripts I will add, so it's not that related :) EDIT: kraifpatrik did an oopsie!
 
Last edited:

kraifpatrik

(edited)
GameMaker Dev.
A new version, 1.0.1, has just been released!
  • Added new enum CE_ECompare that holds possible return values from comparator scripts (in a backwards compatible manner) and updated existing comparator scripts to use the enum.
  • Added new script ce_real_compare for comparing numbers.
  • Added Index - a wrapper around ds_maps designed for holding another maps and retrieving them quickly by their properties. You can think of it as of a simple in-memory database.
  • Added new script ce_ds_map_create_from_array for creating maps from arrays of key-value pairs.
  • Added script ce_ds_list_append for adding values from one list to the end of another list (in-place). For achieving the same effect while creating a new one, you can still use ce_ds_list_merge.
  • Added new script ce_ds_list_map which creates a new list containing the results of calling a given script on every value in the original list.
  • Added new script ce_ds_list_filter which creates a new list containing values from the orignal one for which a given callback script returns true.
  • Added new script ce_ds_list_find_index_last which returns the last index at which the array contains the value.
  • Added new script ce_ds_list_slice which creates a copy of a list, taking values from specified range of indices.
  • Added new scripts ce_ds_list_reduce and ce_ds_list_reduce_right for reducing the list into a single value.
  • Updated documentation of some scripts - added examples.

Index is I think the most notable thing from this update. It is a data structure that allows you to create simple in-memory databases, to which you can add maps and then retrieve ones with specific key-value pairs. Here is a little example.

Code:
// This code creates a database of weapons, searches for all weapons which have
// attack greater than 1 and then prints out their names.
var _weapons = ce_ds_index_create();
var _wKnife = ce_ds_map_create_from_array([
    "name", "Knife",
    "attack", 2
]);
ce_ds_index_add(_weapons, _wKnife);
var _wRustyKnife = ce_ds_map_create_from_array([
    "name", "Rusty Knife",
    "attack", 1
]);
ce_ds_index_add(_weapons, _wRustyKnife);
var _found = ce_ds_index_find(_weapons, "attack", 1, ce_real_compare, CE_ECompare.Greater);
var _size = ds_list_size(_found);
for (var i = 0; i < _size; ++i)
{
    var _item = _found[| i];
    show_debug_message(_item[? "name"]);
}
ds_list_destroy(_found);
 

kraifpatrik

(edited)
GameMaker Dev.
Just released a new version, 1.0.2, mostly focusing on adding new array utility scripts (reaching 228 scripts in total). Here is the changelog:
  • Fixed example in the documentation of ce_ds_list_reduce.
  • Added new script cd_ds_map_get_keys which returns an array of all keys in a ds_map.
  • Added new script cd_ds_map_get_values which returns an array of all values in a ds_map.
  • Added new script ce_ds_list_reverse a new list with values from a given list, but in a reverse order.
  • Added new script ce_array_clone for creating a shallow copy of an array.
  • Added new script ce_array_filter which creates a new array containing values from the orignal one for which a given callback script returns true.
  • Added new scritps ce_array_find_index and ce_array_find_index_last for searching index at which an array contains given value.
  • Added new script ce_array_map which a new array containing the results of calling the script on every value in the given array.
  • Added new script ce_array_merge which joins two arrays into a new one, appending values from the second array to the end of the first array.
  • Added new script ce_array_sort for sorting array in ascending or descending order.
  • Added new scripts ce_array_reduce and ce_array_reduce_right for reducing the array into a single value.
  • Added new script ce_array_reverse which creates a new array with values from the given array, but in a reverse order.
  • Added new scripts ce_real_is_odd and ce_real_is_even to check whether given number is odd or even.
  • Added new script ce_ds_map_extend that shallowly copies key-value pairs from source map to the target map, overwriting the already existing ones.

EDIT: I have created a Discord server dedicated to problem solving in GM using the CE extensions. Invite link here: https://discord.gg/nt5hZWt

EDIT2:
Version 1.0.3 released! This time focusing on optimizations for YYC and documentation, which is now available online at https://kraifpatrik.com/docs/ce.

  • Added new script ce_draw_sprite_nine_slice for drawing 9-slice sprites.
  • A lot of scripts optimized for YYC (the math library especially).
  • Fixed a lot of documentation errors.
  • Created an online documentation, available at https://kraifpatrik.com/docs/ce.
 
Last edited:

kraifpatrik

(edited)
GameMaker Dev.
A new version, 1.1.0, has just been released, bringing more utility scripts as well as an entire new library - Serialize! This new library enables you to serialize object instances into data structures which can be then for example saved on the disk or sent over network and then loaded and deserialized back into instances.

Example of a simple save system using the Serialize library:

Code:
// Save level
var _buffer = buffer_create(1, buffer_grow, 1);
buffer_seek(_buffer, buffer_seek_start, 0);
ce_buffer_write(_buffer, buffer_u32, instance_number(OGameObject));
with (OGameObject)
{
    ce_serialize_to_buffer(OGameObject, _buffer);
}
var _compressed = buffer_compress(_buffer);
buffer_delete(_buffer);
buffer_save(_compressed, "save1.sav");
buffer_delete(_compressed);

// Load level
var _compressed = buffer_load("save1.sav");
var _buffer = buffer_decompress(_compressed);
buffer_delete(_compressed);
buffer_seek(_buffer, buffer_seek_start, 0);
var _instanceCount = buffer_read(_buffer, buffer_u32);
repeat (_instanceCount)
{
    ce_deserialize_from_buffer(_buffer);
}
buffer_delete(_buffer);
Currently the extension contains 242 scripts in total. You can check them all out for free in the online documentation: https://kraifpatrik.com/docs/ce/.

Here is the complete changelog:
  • Added new script ce_string_explode for splitting strings into array at every occurence of a specified delimiter.
  • Added new script ce_ds_map_clone which creates a shallow copy of a map.
  • Added new scripts ce_string_startswith and ce_string_endswith for checking whether string starts/ends with a given substring.
  • Added new script ce_string_format which replaces all occurences of ${identifier} in the string with data from array/map or instance variables.
  • Added new library Serialize which enables you to serialize instances into data structures which can be then for example saved on the disk or sent over network and then loaded and deserialized back into instances.
    • Contains script ce_add_serializable_property which registers object property for serialization.
    • Contains script ce_deserialize_from_array which instantiates an object serialized to an array.
    • Contains script ce_deserialize_from_buffer which instantiates an object serialized to a buffer.
    • Contains script ce_get_serializable_properties which returns a list of object's serializable properties.
    • Contains script ce_serialize_init_global which intializes the serialization functionality.
    • Contains script ce_serialize_to_array which serializes an instance into an array.
    • Contains script ce_serialize_to_buffer which serializes an instance into a buffer.
 

kraifpatrik

(edited)
GameMaker Dev.
Released a new version 1.2.0, bringing another new library - Input! This library enables you to easily define, modify, save & load input schemes by assigning mouse + keyboard or gamepad controls to actions and then check whether any bound key to an action is held down/pressed/released.

The extension currently contains near 300 scripts. You can check them all out for free in the online documentation: https://kraifpatrik.com/docs/ce/.

Here is the complete changelog:
  • Added a new script ce_ds_list_clone which creates a shallow copy of a list.
  • Added a new script ce_ds_list_remove which removes all occurrences of a value from a list.
  • Added a new script ce_ds_list_remove_first which removes the first occurence of a value from a list.
  • Added a new script ce_ds_list_remove_last which removes the last occurence of a value from a list.
  • Moved scripts ce_key_to_string and ce_mouse_to_string to the Input library for sake of consistency.
  • Added a new library Input which enables you to easily define input schemes by binding keyboard + mouse or gamepad controls to actions and then check whether any bound key to an action is held down/pressed/released.
    • Contains script ce_input_action_create which creates a new action.
    • Contains script ce_input_action_get_name which returns a human radable name of an action.
    • Contains script ce_input_encode which encodes input device, type, key and direction into a single number.
    • Contains script ce_input_decode_device which decodes device id from the encoded input.
    • Contains script ce_input_decode_direction which decodes input direction from the encoded input.
    • Contains script ce_input_decode_key which decodes input key from the encoded input.
    • Contains script ce_input_decode_type which decodes input type from the encoded input.
    • Contains script ce_input_scheme_add_action which adds an action to an input scheme.
    • Contains script ce_input_scheme_bind which binds an input to an action within given input scheme.
    • Contains script ce_input_scheme_bind_axis which is a shorthand function to ce_input_scheme_bind for binding gamepad axis.
    • Contains script ce_input_scheme_bind_gamepad which is a shorthand function to ce_input_scheme_bind for binding gamepad buttons.
    • Contains script ce_input_scheme_bind_keyboard which is a shorthand function to ce_input_scheme_bind for binding keyboard buttons.
    • Contains script ce_input_scheme_bind_mouse which is a shorthand function to ce_input_scheme_bind for binding mouse buttons.
    • Contains script ce_input_scheme_bind_mouse_wheel which is a shorthand function to ce_input_scheme_bind for binding mouse wheel.
    • Contains script ce_input_scheme_create which creates a new input scheme.
    • Contains script ce_input_scheme_clear_bindings which removes key bindings of an action within an input scheme.
    • Contains script ce_input_scheme_delete_action which removes an action from an input scheme.
    • Contains script ce_input_scheme_destroy which destroys an input scheme.
    • Contains script ce_input_scheme_get_actions which returns an array of actions contained in an input scheme.
    • Contains script ce_input_scheme_get_name which returns a name of an input scheme.
    • Contains script ce_input_scheme_load which loads an input scheme from a file.
    • Contains script ce_input_scheme_save which saves an input scheme to a file.
    • Contains script ce_input_scheme_unbind which removes given binding from action(s) within a input scheme.
    • Contains script ce_axis_check which checks whether a gamepad axis has given state.
    • Contains script ce_axis_to_string which returns a human readable name of a gamepad axis.
    • Contains script ce_gamepad_check which checks whether a gamepad button has given state.
    • Contains script ce_gamepad_get_input which returns an encoded input that is currently held down on given gamepad.
    • Contains script ce_gamepad_to_string which returns a human readable name of a gamepad button.
    • Contains script ce_keyboard_check which checks whether a keyboard key has given state.
    • Contains script ce_key_to_string which returns a human readable name of a keyboard key.
    • Contains script ce_mouse_check which check whether a mouse button has given state.
    • Contains script ce_mouse_to_string which returns a human readable name of a mouse button.
    • Contains script ce_mouse_wheel_to_string which returns a human readable name of a mouse wheel direction.
    • Contains script ce_input_bind which enables binding of an input to an action within an input scheme.
    • Contains script ce_input_check which checks whether a control for an action within an input scheme has given state.
    • Contains script ce_input_check_down which is a shortcut function for ce_input_check for checking whether a control is held down.
    • Contains script ce_input_check_pressed which is a shortcut function for ce_input_check for checking whether a control is pressed.
    • Contains script ce_input_check_released which is a shortcut function for ce_input_check for checking whether a control is released.
    • Contains script ce_input_config which is a configuration script of the input system.
    • Contains script ce_input_get_binding_action which returns the id of the action the user is currently binding an input to.
    • Contains script ce_input_get_binding_controller which returns the id of the controller that the user is using to bind an input.
    • Contains script ce_input_get_binding_countdown which returns how much time (in ms) is left for the user to bind a control to an action.
    • Contains script ce_input_get_binding_countdown_l which returns a value in range 0..1 saying how much time is left for the user to bind a control to an action.
    • Contains script ce_input_get_binding_scheme which returns the id of the input scheme that the user is binding an input to.
    • Contains script ce_input_get_scheme which returns the id of the current input scheme.
    • Contains script ce_input_init_global which is a global intialization script for the input system.
    • Contains script ce_input_set_scheme which sets an input scheme as the current one.
    • Contains script ce_input_to_string which returns a string containing human readable names of controls bound to an action.
    • Contains script ce_input_update which updates the input system.
    • Contains script ce_input_using_gamepad which returns true if the user is playing on a gamepad.

I'm also putting on a discount for a limited time! If this update got you interested in the extension, you can get it from the Marketplace.

EDIT: Released an example project for the input library!

Source: https://kraifpatrik.com/docs/ce/download/InputExample.yyz
Executable: https://kraifpatrik.com/docs/ce/download/InputExample.zip

EDIT2: I have now created a public Trello board for CE Core, where you can see what I'm working on. You can check it out at https://trello.com/b/1D3NWmle/ce-core.

EDIT3: A hotfix version 1.2.1 has been released on July 25th, 2019, fixing object serialization and string join functions.

  • Hotfix of ce_serialize_to_array and ce_serialize_to_buffer, they took a wrong object_index and so they didn't work when not used in a with clause.
  • Hotfix of ce_string_join, ce_string_join_array and ce_string_join_list, they didn't work when given 0 arguments/an empty data structures.
  • Fixed few typos in the documentation.
 
Last edited:

kraifpatrik

(edited)
GameMaker Dev.
Released new version 1.2.2, which brings multiple fixes and improvements to the Input library and a new utility library Iter, which simulates foreach iterator from other programming languages.

Following code iterates through the array, skipping index 1 and breaking at index 2, so it prints only '0:1' and '2:3' to the console.

Code:
var _arr = [1, 2, 3, 4];
while (ce_iter(_arr))
{
    if (CE_ITER_INDEX == 1)
    {
        CE_ITER_CONTINUE;
    }
    show_debug_message(
        ce_string_format("${0}: ${1}", [CE_ITER_INDEX, CE_ITER_VALUE]));
    if (CE_ITER_INDEX == 2)
    {
        CE_ITER_BREAK;
    }
}
Here is the changelog.

  • Added new script ce_object_get_base which returns the index of the base object in an object's ancestors hierarchy.
  • Added new script ce_ds_map_extend_from_array which extends a map by key-value pairs stored in an array.
  • Added new script ce_ds_map_find_key which finds the first key of the map that contains given value.
  • Scripts ce_ds_list_remove_first and ce_ds_list_remove_last now return true if the value was in the list or false if it was not. Previously the return value was not defined.
  • Updates to the Input library:
    • Mouse & keyboard input now works only for the main controller. This enables you to have for example a local multiplayer where one of the player is using the mouse & keyboard and others a gamepad.
    • Added scripts ce_input_get_main_gamepad and ce_input_set_main_gamepad for getting and settings the id of the main gamepad.
    • Added script ce_input_assign_gamepad which enables you to assign a gamepad to an instance. If an instance has a gamepad assigned to it, then it doesn't have to explicitly pass it to the ce_input_check* scripts.
    • Added script ce_input_get_assigned_gamepad which returns the id of the gamepad assigned to an instance.
    • Added script ce_input_get_assigned_instance which returns the id of the instance assigned to a gamepad.
    • Added events CE_EV_GAMEPAD_CONNECTED and CE_EV_GAMEPAD_DISCONNECTED which are triggered when a gamepad is connected / disconnected.
    • Added configuration macro CE_INPUT_RECOGNIZE_MAIN_GAMEPAD to enable / disable automatical recognition of main gamepad upon game start. This will be now by default set to false! It is suggested to set the main gamepad manually using the CE_EV_GAMEPAD_CONNECTED for example.
    • Added configuration macro CE_INPUT_RECOGNIZE_MOUSE_MOVEMENT to enable / disable taking into account mouse movement when determining whether the player is using a gamepad or a mouse and keyboard. This is by default set to true.
    • Fixed script `e_input_check_down, ce_input_check_pressed and ce_input_check_released. They were incorrectly reading the controller argument, so it always defaulted to the main one.
    • Mouse & keyboard controls now only work checking input of the main controller. This allows for local multiplayer where one player can use the mouse & keyboard and others gamepads.
  • Added new utility Iter for iterating data structures. This currently supports arrays, lists and maps. Nested iterators are supported.
    • Contains script ce_iter which iterates over data structures.
    • Contains script ce_iter_config which defines macros CE_ITER_INDEX (the current index in the iteration), CE_ITER_VALUE (the current value in the iteration), CE_ITER_BREAK (breaks the current iteration, equivalent of break) and CE_ITER_CONTINUE (goes to the next step in the iteration, equivalent of continue).
    • Contains script ce_iter_init_global which is the global initialization script for the Iter utility.
 
Last edited:

kraifpatrik

(edited)
GameMaker Dev.
Hey everyone, today I'm releasing a new version 1.3.0 of the extension, bringing you new features that I'm personally very excited about.

Custom class system
I've createad a custom class system using maps. It has support for inheritance, final classes (classes which cannot be further inherited), inheritance checks (you can check if given instance inherits from some class), casting instances from their class to another class which they inherit from, property calls (simple single parameter methods) including super, property getters & setters and destructors, which are scripts called automatically when an instance of a class is deleted.

Here is a little example.

Code:
/// @func shape_class()
/// @desc Defines a class *shape*, which is the base class for geometric shapes.
CE_PRAGMA_ONCE;
var _shapeClass = ce_class_create();
ce_class_define_properties(_shapeClass, [
    // Shape's position on the x axis.
    "x", 0,
    // Shape's position on the y axis.
    "y", 0,
    // A script which returns the area of the shape.
    "getArea", undefined,
]);

/// @func circle_class()
/// @desc Defines a class *circle* which inherits from the *shape* class.
CE_PRAGMA_ONCE;
var _circleClass = ce_class_create(shape_class);
ce_class_define_properties(_circleClass, [
    // The radius of the circle.
    "radius", 0,
    "getArea", circle_get_area,
]);

/// @func circle_create(x, y, radius)
/// @desc Creates a new instance of a class *circle*.
var _circle = ce_make_instance(circle_class);
ce_set_prop(_circle, "x", argument0);
ce_set_prop(_circle, "y", argument1);
ce_set_prop(_circle, "radius", argument2);
return _circle;

/// @func circle_get_area(circle)
/// @return {real} The area of the circle.
return pi * sqr(ce_get_prop(argument[0], "radius"));

/// @desc Test
var _circle = circle_create(10, 10, 100);
ce_is_instance(_circle, circle_class); // => true
ce_is_instance(_circle, shape_class); // => true
ce_is_instance(_circle, some_other_class); // => false
ce_call(_circle, "getArea"); // => 31415.92
var _shape = ce_cast(_circle, shape_class);
ce_call(_shape, "getArea"); // => undefined
// ce_cast(_circle, some_other_class); // Would end with an error
ce_delete(_circle);
Component system
Using the class system, I've created a component system which allows you to write game logic in form of components. These components can be then added and removed from object instances on runtime. The motivation behind this system was to be able to easily share code between different objects which do not have and cannot have a common ancestor (because of no multiple inheritance). The system also includes handy scripts like getting a list of components that an instance has or getting indices of all objects that have / had given components. You can see the full list of functions in the changelog at the bottom of this post.

Here is an example of a timer component, which allows you to trigger a callback script and / or a custom event after given number of milliseconds. This component is included in the update.

Code:
/// @desc Create event
// Initialize the component system within the instance
ce_init_components();
// Add the timer component
timerComponent = ce_add_component(ce_timer_component);
// Create a timer for spawning instances
spawnObject = OEnemy;
spawnInterval = ce_seconds_to_ms(30);
timerSpawn = ce_add_timer(timerComponent, spawnInterval);

/// @desc Step event
ce_call_components("onUpdate");

/// @desc User event
switch (ce_get_event())
{
case CE_EV_TIMEOUT:
    if (ce_get_event_data() == timerSpawn)
    {
        // Spawn an instance on timeout and create a new timer
        instance_create_layer(layer, random(room_width), random(room_height),
            spawnObject);
        timerSpawn = ce_add_timer(timerComponent, spawnInterval);
    }
    break;
}

/// @desc Clean up event
ce_destroy_components();
This update also includes another two components - state machine component and depth sort component. The state machine component, as the name suggests, allows you to easily define state machines and the depth sort component is for sorting instances in the same manner as depth=-y did in the older versions of GameMaker, but using layers.

Scripts reorganization
When I've first released the extension CE Core, I've had a little bit different plans on what it's going to be and it made sense to put everything into Scripts > CE > Core folder. But since then the extension has been growing bigger and the Core subfolder started to cramp up and it didn't represent what the core of the extension really is anymore. So in this update, I've decided to only keep libraries Assert, Class, CustomEvents, Macros and Types (from the Utils) in the Core folder, and put everything else directly underneath CE. This makes the Core contain libraries that form the base foundation of the extension, plus it should also make it easier to include only libraries that you want to use in your project.

Near future plans
The extension now contains 367 scripts and it's not just random utilities anymore. It's starting to grow into a full game framework with complex systems which need to be explained. That is something that I would like to focus on in the near future - create a guide to accompany the scripting API documentation, create more examples and tutorials etc. Till that's finished, please join the dedicated Discord where you can ask me anything regarding the extension and I will try to do my best to help you out if you have any problems with it. Or if you are interested in the development progress, you can also check out the public Trello board. Cheers!

Full changelog
  • Reorganized scripts folders into more logical units. The 'Core' folder now contains only scripts that form the base foundation for other libraries. This should make it easier to import only libraries that you need.
  • Added new script ce_get_current_script which gets a script index from the callstack.
  • Added new library Class which simulates classes using maps. It has support for inheritance, final classes (classes which cannot be further inherited), inheritance checks, casting, (superclass) property calls, property getters & setters and destructors.
    • Contains script ce_call which calls script_execute with object's property value, object's id and optionally additional data as its arguments.
    • Contains script ce_cast which an instance of some class (object) to another class, which it must inherit from or be identical with.
    • Contains script ce_class_of which retrieves a class of an object.
    • Contains script ce_class_create which creates a new class descriptor.
    • Contains script ce_class_define_destructor which defines a destructor of a class.
    • Contains script ce_class_define_property which defines a property of a class.
    • Contains script ce_class_define_properties which defines multiple properties of a class.
    • Contains script ce_class_init_global which is the global initialization script of the class system.
    • Contains script ce_delete which destroys an instance of a class (object), calling its destructor, then its superclass destructor etc.
    • Contains script ce_get_prop which retrieves a value of object's property.
    • Contains script ce_has_prop which checks whether an object has own or inherited property.
    • Contains script ce_has_own_prop which checks whether an object has own property.
    • Contains script ce_is_instance which checks whether an object is an instance of a class or if it inherits from it.
    • Contains script ce_make_instance which creates a new instance (object) of a class.
    • Contains script ce_set_prop which sets value of object's property.
    • Contains script ce_super which calls script_execute with object's inherited property value, object's id and optionally additional data as its arguments.
    • Contains script ce_superclass_of which retrieves a superclass of an object.
  • Added new library Component which allows you to define game logic in form of components, which then can be added to and removed from object instances.
    • Contains class component, which is the base class for all components.
      • Contains script ce_component_class which contains the definition of the component class.
      • Contains script ce_component_config which is the configuration script for the component system.
    • Contains class depth sort component which allows you to change draw order of instances by putting them into separate layers based on their depth.
      • Contains script ce_create_depth_layers which creates layers for depth sort components.
      • Contains script ce_depth_sort_component which contains the definition of the depth sort component class.
      • Contains script ce_depth_sort_component_config which is the configuration script for the depth sort component.
      • Contains script ce_depth_sort_component_init_global which is the global initialization script for the depth sort component.
      • Contains script ce_depth_sort_component_on_add which is a script executed when an instance of a depth sort component is added to an object instance.
      • Contains script ce_sort_by_depth which sorts an instance containing given depth sort component by given value.
    • Contains class state machine component which allows you to easily create state machines.
      • Contains script ce_change_state which changes state of a state machine component and triggers respective custom event.
      • Contains script ce_get_state which retrieves the current state of a state machine component.
      • Contains script ce_set_state which changes state of a state machine component without triggering a custom event.
      • Contains script ce_state_create which creates a new state of a state machine component.
      • Contains script ce_state_machine_component which contains the definition of the state machine component class.
      • Contain script ce_state_machine_component_config which is the configuration script of the state machine component.
    • Contains class timer component which enables you to define timers which can trigger a callback script and / or a custom event after certain number of milliseconds.
      • Contains class timer which are added to and managed by timer component instances.
        • Contains script ce_timer_class which contains the definiton of the timer class.
        • Contains script ce_timer_create which creates a new instance of the timer class.
        • Contains script ce_timer_get_callback which retrieves the index of the callback script of a timer.
        • Contains script ce_timer_get_paused which checks whether a timer is paused.
        • Contains script ce_timer_get_time_left which retrieves a time left till a timer ends.
        • Contains script ce_timer_on_update which handles logic of a timer instance.
        • Contains script ce_timer_set_paused which pauses or unpauses a timer based on given arguments.
      • Contains script ce_add_timer which adds a timer to a timer component instance.
      • Contains script ce_delete_timer which deletes a timer.
      • Contains script ce_timer_component which contains the definition of the timer component class.
      • Contains script ce_timer_component_config which is the configuration script of the timer component.
      • Contains script ce_timer_component_create which creates a new instance of the timer component class.
      • Contains script ce_timer_component_delete which is the destructor of the timer component class.
      • Contains script ce_timer_component_on_init which initializes an instance of the timer component class.
      • Contains script ce_timer_component_on_update which handles logic of a timer component instance.
    • Contains script ce_add_component which adds a component to an instance and triggers respective custom event.
    • Contains script ce_call_components which executes ce_call on each of instance's components.
    • Contains script ce_destroy_components which destroys all components of an instance.
    • Contains script ce_get_component which retrieves instance's component of given class.
    • Contains script ce_has_component which checks whether an instance has a component of given class.
    • Contains script ce_init_components which initializes the component system within the calling instance.
    • Contains script ce_list_components which retrieves a read-only list of components of an instance.
    • Contains script ce_objects_with_component which creates a list containing objects (not instances) which have or had given components.
    • Contains script ce_remove_component which removes a component from an instance and triggers respective custom event.
 
Last edited:

kraifpatrik

(edited)
GameMaker Dev.
Updates on progress: I've released a new version 1.3.1 on August 19, 2019. It was a little update, mostly fixing issues with the XML library caused by the GML consistency update. Also since this version I've decided to not post full changelogs here anymore, as it's a lot of tedious works to change it from markdown to the forum format and I could spend the time more productively. Instead from now on you can always find the full changelog at https://kraifpatrik.com/docs/ce/ChangelogLatest.html. As I said in the previous update, I'm currenty working on the manuals for all the different systems. So far I've finished manuals for the Class system, the Event system, the Input system and the XML library. Next up will be components and serialization (in an unspecified order, but I expect the components to take much more time). When that is done, you can expect me to get back on working on new updates to the library. If you would like to, you can come chat with me about the extension in its dedicated Discord or follow its development progress on the public Trello board.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
as it's a lot of tedious works to change it from markdown to the forum format
You can copy text from your site to forum (when in WYSIWIG editor mode) with minimal loss of formatting:
Changelog 1.3.1
  • Added new script ce_parse_real which parses a real number from a string. This function returns NaN if given string does not represent a number instead of ending the game with an error.
  • Added new script ce_real_to_string which converts a real value to a string without generating trailing zeros after a decimal point.
  • Updated ce_xml_read to use the new ce_parse_real script for parsing element attributes.
  • Updated ce_xml_string to use the new ce_real_to_string script.
  • Moved Types folder from Core back to Utils, since it contains only ce_is_nan, which GML already supports.
 

kraifpatrik

(edited)
GameMaker Dev.
Updates: Since 5th September it is possible to send feedback for pages of the documentation - just click one of the "Yes" or "No" buttons under the "Do you find this page helpful?" question at the bottom of the page and then a little window pops up where you can optionally write a message and then click the "Send" button. Your feedback is very welcome and I will do my best to improve the documentation based on it! Also, starting today the extension is available to purchase from itch.io: https://kraifpatrik.itch.io/ce-core.

 

kraifpatrik

(edited)
GameMaker Dev.
Manual for the component system is finally up! You can find it at https://kraifpatrik.com/docs/ce/ComponentSystem.html. Personally I'm really happy about how the system came out and I can't wait till I have all the manuals for the current libraries done, so I can finally work on more cool components and new updates to the extension.



EDIT: Serialize is a little library with just a few scripts, so writing a manual for that was really quick! And now it's available on https://kraifpatrik.com/docs/ce/Serialize.html!
 
Last edited:

kraifpatrik

(edited)
GameMaker Dev.
Creating input streams using the class system

Hey everyone,

today I would like to share with you a better, more pratical, real-world example of what the CE Core's class system can be used for. As you know, CE Core contains an XML parser, but right now the parser allows only to read files, because in pure GML (well, CE Core is also pure GML, I think you know what I mean) reading bytes from strings and files is handled separately. This what the parser's code looks like now:

Code:
/// @func ce_xml_read(fileName)
var _file = file_bin_open(argument0, 0);
var _root = noone;

if (_file == -1)
{
    return _root;
}

var _filePos = 0;
var _fileSize = file_bin_size(_file);

do
{
    var _byte = file_bin_read_byte(_file);
    // Build XML tree nodes here...
}
until (++_filePos == _fileSize);

file_bin_close(_file);

return _root;
Technically we could just throw in there a bunch of if statements and parameters that would handle using different functions based on whether we are parsing a string or a file, but the code would then become a big pile of mess and it wouldn't help us if we ever needed to do something similar in the future. A much better approach would be to create an abstraction on input streams which would just provide us with some "get size" and "read byte" methods and hide the specifics. And that's one of the virtually unlimited things that we can do with the class system!

Firstly we will create a base class for all input streams:

Code:
/// @func ce_input_stream_class()
CE_PRAGMA_ONCE;

var _inputStreamClass = ce_class_create();
ce_class_define_properties(_inputStreamClass, [
    // Current position in the input stream.
    "index", 0,
    // The size of the input stream.
    "size", 0,
    // Initialization method for factory scripts.
    "_init", undefined,
    // Returns number of available bytes to read.
    "available", ce_input_stream_available,
    // Returns a byte from the input stream and increments the current position.
    "read_byte", undefined,
]);

/// @func ce_input_stream_available(id)
var _inputStream = argument[0];
return ce_get_prop(_inputStream, "size") - ce_get_prop(_inputStream, "index");
We don't want to instantiate this class, se we won't care about providing its constructors. Now we can create a file input stream class, which will inherit from the base class and provide implementation specific for files.

Code:
/// @func ce_file_input_stream_class()
CE_PRAGMA_ONCE;

var _fileInputStreamClass = ce_class_create(ce_input_stream_class);
ce_class_define_properties(_fileInputStreamClass, [
    // The file that we will be reading from.
    "file", noone,
    // This will initialize the "size" property.
    "_init", ce_file_input_stream_init,
    "read_byte", ce_file_input_stream_read_byte,
]);
// The destructor will close the file when the file input stream is deleted.
ce_class_define_destructor(_fileInputStreamClass, ce_file_input_stream_delete);

/// @func ce_file_input_stream_init(fileInputStream)
var _fileInputStream = argument[0];
ce_super(_fileInputStream, "_init");
var _size = file_bin_size(ce_get_prop(_fileInputStream, "file"));
ce_set_prop(_fileInputStream, "size", _size);

/// @func ce_file_input_stream_read_byte(fileInputStream)
var _fileInputStream = argument[0];
var _index = ce_get_prop(_fileInputStream, "index");
ce_set_prop(_fileInputStream, "index", _index + 1);
return file_bin_read_byte(ce_get_prop(_fileInputStream, "file"));

/// @func ce_file_input_stream_delete(fileInputStream)
file_bin_close(ce_get_prop(argument0, "file"));
For the file input stream we will need a constructor:

Code:
/// @func ce_file_input_stream_create(fileInputStream)
var _file = file_bin_open(argument0, 0);
if (_file == -1)
{
    return noone;
}

var _fileInputStream = ce_make_instance(ce_file_input_stream_class);
ce_set_prop(_fileInputStream, "file", _file);
ce_call(_fileInputStream, "_init");
return _fileInputStream;
Now we can create an implementation of a string input stream, which will do the same, but for strings. For this one we will have to count with that strings are indexed from 1 instead of 0.

Code:
/// @func ce_string_input_stream_class()
CE_PRAGMA_ONCE;

var _stringInputStreamClass = ce_class_create(ce_input_stream_class);
ce_class_define_properties(_stringInputStreamClass, [
    // The string that we will be reading.
    "string", undefined,
    // This will intitialize the "index" and "size" properties.
    "_init", ce_string_input_stream_init,
    // Since strings are indexed from 1, we have to redefine this method as well.
    "available", ce_string_input_stream_available,
    "read_byte", ce_string_input_stream_read_byte,
]);

/// @func ce_string_input_stream_init(stringInputStream)
var _stringInputStream = argument[0];
var _string = ce_get_prop(_stringInputStream, "string");
var _size = string_length(_string);
ce_set_prop(_stringInputStream, "size", _size);
ce_set_prop(_stringInputStream, "index", 1);

/// @func ce_string_input_stream_available(stringInputStream)
var _stringInputStream = argument[0];
return (ce_get_prop(_stringInputStream, "size")
    - ce_get_prop(_stringInputStream, "index") + 1);

/// @func ce_string_input_stream_read_byte(stringInputStream)
var _stringInputStream = argument[0];
var _index = ce_get_prop(_stringInputStream, "index");
ce_set_prop(_stringInputStream, "index", _index + 1);
return string_byte_at(ce_get_prop(_stringInputStream, "string"), _index);
This is what the string input stream constructor will look like:

Code:
/// @func ce_string_input_stream_create(string)
var _stringInputStream = ce_make_instance(ce_string_input_stream_class);
ce_set_prop(_stringInputStream, "string", argument0);
ce_call(_stringInputStream, "_init");
return _stringInputStream;
And after we modify the XML parser to use input streams

Code:
/// @func ce_xml_read(inputStream)
var _inputStream = argument0;
var _streamPos = 0;
var _streamSize = ce_call(_inputStream, "available");
var _root = noone;

do
{
    var _byte = ce_call(_inputStream, "read_byte");
    // Build XML tree nodes here...
}
until (++_streamPos == _streamSize);

return _root;
we can parse XML from both files and strings!

Code:
var _fileInputStream = ce_file_input_stream_create("test.xml");
var _xml = ce_xml_read_input_stream(_fileInputStream);
show_debug_message(ce_xml_write(_xml));
ce_delete(_fileInputStream);

var _stringInputStream = ce_string_input_stream_create(@"
    <root>
        <some>
            <nodes>here</nodes>
        </some>
    </root>");
var _xml = ce_xml_read_input_stream(_stringInputStream);
show_debug_message(ce_xml_write(_xml));
ce_delete(_stringInputStream);
And what's even better, the XML parser is now ready to parse any input stream ever, without doing any modifications to it, all we have to do is just provide specific implementation of the input stream. And additionally, in the future we don't have to be bothered by files vs strings vs buffers vs you-name-it ever again, we can just use the input stream class and make our functions work on anything!

There is just so much stuff that can be done using the class system, but unfortunately I can't put it all into a single extension, because it would just get too big and not everyone needs everything. One of the things that I would like to do in the future is make a website and a client where you could download these handy classes etc. in form of packages, including their dependencies. I think that would be really cool.

Alright, thank you for reading, I hope you liked it, see you next time!
 
Last edited:

kraifpatrik

(edited)
GameMaker Dev.
Hey everyone,

after much thought, I've decided to release the full source code of CE Core under the MIT license on GitHub. I believe this way the extension can help our community a lot more, which is why the extension was publicly released in the first place. I'm really thankful to all who have bought the extension and I hope they are not disappointed by my decision of releasing it for free. For those who like my work and who would like to support me in developing the extension, you can still purchase it on the Marketplace, where I have lowered the price to $10, or on itch.io, where it is available under the pay what you want model ($10 being only the recommended price). I still have some big plans for the extension and I'm really thankful for any support, as it enables me to put more time into the development and to deliver a better product. If you have any questions or need help with something regarding CE Core, feel free to ask me here, or you can also join its dedicated Discord, where I can help you out in real-time.

Cheers!
 
Last edited:

kraifpatrik

(edited)
GameMaker Dev.
Updates: I'm currently splitting the GitHub repository into multiple smaller ones, each representing a library. The libraries can then be included into your projects using Catalyst, the open-source package manager for GMS2 by @DukeSoft. This way it will be much easier to include only libraries that you need, including their dependencies, without any hassle.

 
Last edited:

kraifpatrik

(edited)
GameMaker Dev.
Alright, the repository splitting is done! The project will be now called only CE and you can find its new home at https://github.com/kraifpatrik/ce. The old repository of CE Core is still available here and it will be kept for legacy purposes, but new versions won't be released as a single extension anymore. I have put the extension as "off sale" on the Marketplace and itch.io as well, so people who have it from there can still download it, but it's not available for purchase anymore. I'm also removing mentions of CE Core, the Marketplace and the itch.io links from the repo, the docs, the Discord server etc. so if you still find any, please let me know. I've also updated the first post in here so don't forget to check it out for new info. Cheers!
 
Last edited:

❤️×1

Member
I'm kinda worried @kraifpatrik left the community : their site, itch.io, twitter, discord and everything else has been wiped clean. But their overall work and CE in particular is a great resource! With that in mind, I wanted to make documentation easily accessible again, it's built from the latest version of CE (1.3.1) and you can download it here : https://www.mediafire.com/file/nb1njzgz2rq181p/CE_Doc.zip/file

Hoping it's only a temporary break and he'll be back soon, otherwise I'll do my best to maintain CE myself, especially with the upcoming GML update, but I don't have 10% of kreifpatrik's skills so it won't ever be as elegant.
 

rIKmAN

Member
I can't see where they said anything beside rebranding CE Core to CE and removing mentions of CE Core.
I'm not sure I'm understanding what you're asking, but it says in the post I mentioned "I have put the extension as "off sale" on the Marketplace and itch.io as well, so people who have it from there can still download it, but it's not available for purchase anymore." and "I'm also removing mentions of CE Core, the Marketplace and the itch.io links from the repo, the docs, the Discord server etc." which seems to relate to what you are saying about things being removed from those places.

I've not used it but it seems like it's gone from a paid asset into a free asset, been rebranded and moved to github and Catalyst as described in the OP and CE Core is now the old version hosted for legacy purposes. The new docs etc are also linked in the OP for the latest version.

That's what I get from reading that post and the edited OP anyway.
 

❤️×1

Member
That's what I get from reading that post and the edited OP anyway.
Yeah but... You're not reading what I wrote: since then, after the switch to open source, @kraifpatrik suddenly closed their website, twitter account, itch.io account, discord server... all their online presence is pretty much gone.
 

rIKmAN

Member
Yeah but... You're not reading what I wrote
I did read what you wrote, but as I said - I wasn't sure I understood what you were asking.
It seems you were talking more about his general online presence and personal accounts being removed rather than anything to do specifically with CE.

Bit strange but hope all is good with him.
 
Top