CollageDrawer - coldrockgames/gml-raptor GitHub Wiki
Similar to the CanvasDrawer, this object draws surfaces, but it does it in a smart way.
You can see a full example of the builder chain for the collage subsystem at Collage Builder Example.
The base for this object is the MIT licensed Collage Library by tabularElf.
He created a library with a great idea: Build entire texture pages at runtime. It is a good concept, and while we had to change lots of code in the library and fix many bugs, the core idea and the GPU- and render-mechanics of the library are great. At the time of writing this, we used a code base with version number 0.5, more or less a prototype, but it was all that was available, so we adapted it and integrated it into raptor.
In GameMaker, using sprite_add
always creates a new texture page for the sprite. So, in a dynamic game, where you maybe load hundred sprites or more, you will have a hundred texture swaps per frame. This is going to kill your performance sooner or later and Collage targets exactly this problem: Put all those together on one texture page, thus removing dozens of texture swaps.
You create a compilation, a series of images, sprites, files, file strips, surfaces, even whole sprite-sheets with several rows and columns and multiple sprites on one sheet and images from the internet and the library will pack them together onto one single texture page (to be more exact: to as many texture pages as you tell it to).
This is the game object that brings your collages to life. It renders any sprite contained in any collage with only three variable definitions:

Variable | Description |
---|---|
collage_name |
The name of the collage to use |
sprite_name |
The name of the sprite in the named collage to render |
It's as easy as that!
In contrast to the original source code of collage, we removed many double definitions in the library. You work normally with the "green" variables, like image_speed, image_index, fps, image_angle and all those. Also the scaling is simply taken from the green variables, so you can place your drawer either directly in the room and apply the settings or you create it in code, or you just skin it. Yes! As the drawer is a raptor object, it is fully skinnable, respects themes and can even be initialized through the Raptor RichJson Format in a data file. This means, it can be hot-patched through a download from your game server without any restrictions and assumptions (like squared sprites in a file strip).
We removed the public interface from collage and created a builder pattern syntax to interact with the library. This gives you a consistent way to create the content and completely removes the need to care about async events in HTML mode or image downloads from your server. It is all handled internally by raptor, even the async callbacks. You just don't need to care.
You start interacting with collage through the COLLAGE
macro, which resolves to a (singleton) CollageManager
instance. This is the interface class we created to interact with the library.
It offers these methods:
Set the "focus" of the CollageManager to the name of the collage you specify with this function. This does not create the collage for you, as creating requires more information. See the create
method below.
You don't need to care about batching anymore. The CollageManager
keeps track of all batches and finishes or creates batches for you.
The collage, you activate with this function is now referred to as the selected collage for the following function definitions.
/// @func for_collage(_name)
/// @desc Begin a chain for the collage identified by _name
static for_collage = function(_name) {
Creates a new collage instance. This method is "safe" to call. If the selected collage already exists, this function does not destroy or overwrite it, it just returns in this case. So you may run through your builder tree multiple times without creating zombie instances.
/// @func create(
/// _width = 4096, _height = 4096,
/// _crop = __COLLAGE_DEFAULT_CROP,
/// _margin = 0,
/// _optimize = __COLLAGE_DEFAULT_OPTIMIZE)
/// @desc Create a new collage with the specified data,
/// ONLY IF IT DOES NOT ALREADY EXIST!
/// To recreate a collage, use .destroy().create()
/// NOTE: This function also starts batching mode.
static create = function(
_width = 4096, _height = 4096,
_crop = __COLLAGE_DEFAULT_CROP,
_margin = 0,
_optimize = __COLLAGE_DEFAULT_OPTIMIZE) {
/// @func destroy()
/// @desc Destroys the currently selected collage
static destroy = function() {
/// @func clear()
/// @desc Remove all images and reset the selected collage
static clear = function() {
/// @func get(_collage_name)
/// @desc Retrieve the collage instance stored as _collage_name
/// NOTE: This retrieves the collage instance from the original library
static get = function(_collage_name) {
/// @func exists(_collage_name)
/// @desc Checks whether a collage with the specified name exists
static exists = function(_collage_name) {
/// @func sprite_exists(_name)
/// @desc Check whether a sprite with the given name exists in the collage
static sprite_exists = function(_name) {
/// @func sprite_sheet_exists(_name)
/// @desc Check whether a sprite sheet with the given name exists in the collage
static sprite_sheet_exists = function(_name) {
Pushes to or removes a collage from graphics card's memory.
/// @func push_to_vram()
/// @desc Preload all texture pages of the current collage into graphics card memory
static push_to_vram = function() {
/// @func remove_from_vram()
/// @desc Free memory on the graphics card by unloading all pages of this collage
static remove_from_vram = function() {
/// @func is_waiting_for_async_images()
/// @desc Returns whether any async manager still waiting for images to be loaded
static is_waiting_for_async_images = function() {
As every builder pattern, you close your command chain by invoking the .build()
method.
Note
As the Manager is capable of downloading images from the internet and also works on HTML5, where every image access is asynchronous by definition, the build() method may block until all images arrived from their content source.
/// @func build()
/// @desc build all the data into texture pages
static build = function() {
While we expose access to collage's batch methods, we recommend, that you let the CollageManager do the hard work and manage batching for you. The raptor version of the library is designed to provide you a transparent way to "just add your images to the collage" without having to think too deep about the details. Batch mode is activated and deactivated for you, but you are allowed to override the behavior if needed.
/// @func start_batch()
/// @desc Begin a batch on the selected collage
static start_batch = function() {
/// @func clear_batch()
/// @desc Clear the current batch on the selected collage
static clear_batch = function() {
/// @func finish_batch(_crop = true)
/// @desc Finish the current batch for the selected collage,
/// optionally crop any unused space around the textures (default: true)
static finish_batch = function(_crop = true) {
/// @func is_in_batch_mode()
static is_in_batch_mode = function() {
Calling this function creates a new builder pattern to set up your sprite sheet. The pattern ends by adding .build()
to the chain.
For details about sprite sheets see CollageSpriteSheet.
/// @func add_spritesheet(_name, _filename)
/// @desc Add a new SpriteSheet to the collage
static add_spritesheet = function(_name, _filename) {
/// @func add_sprite(_name, _index, _separate_texture = false)
/// @desc Add an existing sprite to the collage
/// The _index parameter must be a valid sprite_index known to the game, not a filename!
static add_sprite = function(_name, _index, _separate_texture = false) {
/// @func add_file(
/// _name, _filename,
/// _xorigin = 0, _yorigin = 0,
/// _remove_back = false,
/// _smooth = false, _separate_texture = false)
/// @desc Add a new single frame sprite from an external image file to the collage
static add_file = function(
/// @func add_file_strip(
/// _name, _filename,
/// _frame_count = 1, _fps = 0,
/// _xorigin = 0, _yorigin = 0,
/// _remove_back = false,
/// _smooth = false, _separate_texture = false)
/// @desc Add a new sprite to the collage from a filestrip image file
static add_file_strip = function(_name, _filename, _frame_count = 1, _fps = 0,
/// @func add_surface(
/// _name, _filename,
/// _xorigin = 0, _yorigin = 0,
/// _remove_back = false,
/// _smooth = false, _separate_texture = false)
/// @desc Add a new single frame sprite to the collage from a surface
static add_surface = function(
/// @func add_surface_part(
/// _name, _surface,
/// _x, _y, _w, _h,
/// _xorigin = 0, _yorigin = 0,
/// _remove_back = false,
/// _smooth = false, _separate_texture = false)
/// @desc Add a new single frame sprite to the collage from a part of a surface
static add_surface_part = function(
/// @func add_surface_strip(
/// _name, _surface,
/// _frame_count = 1, _fps = 0,
/// _xorigin = 0, _yorigin = 0,
/// _remove_back = false,
/// _smooth = false, _separate_texture = false)
/// @desc Add a new single frame sprite to the collage from a surface
static add_surface_strip = function(
/// @func get_texture_page(_index)
/// @desc Return the texture page at the given index from the current collage
static get_texture_page = function(_index) {
/// @func get_texture(_index)
/// @desc Return the texture (surface) of the page at the given index
static get_texture = function(_index) {
/// @func get_page_count()
/// @desc Return the number of texture pages in the current collage
static get_page_count = function() {
/// @func get_image_array(_sorted = false)
/// @desc Return an array of all image objects in the collage; optionally sorted
static get_image_array = function(_sorted = false) {
/// @func get_sprite_names()
/// @desc Return an array of all sprite names in the collage
static get_sprite_names = function() {
/// @func get_sprite_sheet_names()
/// @desc Return the names of all sprite sheets known to the manager
static get_sprite_sheet_names = function() {
/// @func get_sprite(_sprite_name)
/// @desc Retrieve the sprite with the specified name
/// or undefined, if not found
static get_sprite = function(_sprite_name) {
return vsget(__sprites, _sprite_name);
}
/// @func get_sprite_sheet(_spritesheet_name)
/// @desc Retrieve the sprite with the specified name
/// or undefined, if not found
static get_sprite_sheet = function(_spritesheet_name) {
return vsget(__spritesheets, _spritesheet_name);
}