-
Notifications
You must be signed in to change notification settings - Fork 1
Core
Jump To | back |
Overview | Contents | Macros | Index |
---|
The Core module of FAST is what all other modules build on top of. It contains a series of low-level foundations and common functions such as data structures, a common event system, and a string parser. The Core module contains the only object used by FAST, __FASTtool
. This object is not required for most features to work, and can be removed/disabled by setting FAST_DISABLE_EVENTS
to true
, however doing so may require managing event features yourself, such as manually calling for Loggers to close on exit.
Events are essentially methods that are bound to a specific timing. You can create events that will happen once after a number of frames, repeat after so many frames, or even ones that should happen 10 seconds from now. There are two event types FrameEvent and DeltaEvent. The two are identical except for how they measure when they should activate. Unsurprisingly, FrameEvents are based on frame-timing, and DeltaEvents are delta-timing. You can create an event by calling new
on one of these constructors:
event = new FrameEvent( FAST.STEP, 1, undefined, function() {
show_debug_message( "Hello World!" );
}
This would create an event that will print, "Hello World!" to the console every frame. If you'd like an event to only happen once, you can call once()
on the event, event when it's created:
event = new DeltaEvent( FAST.STEP_BEGIN, 10, undefined, function() {
show_debug_message( "Hello Once!" ):
}).once();
Additionally, you can use now()
if you would like the event to fire as soon as it is created. Since events are called via the FAST system, it isn't possible to know when during a step the event will be called. Thus this should generally only be used when you are sure that the event will not run during this frame.
Lastly, it's important to understand that the method that is passed to the event will be run at the scope it was bound to. This is highly convenient because it means you can write your Events as if they were running at the scope they were defined, but this means you should remember to clean up any events an instance or structure created when they are destroyed. You can use method()
to bind a function to a different scope when a Event is created as well.
name = "FAST";
event = new FrameEvent( FAST.STEP, 1, undefined, function() {
// this method will run as if it were part of the previous scope
show_debug_message( name );
}
Publishers are used to distribute "messages" to "subscribers". Like Events, methods are bound to channels and notified when called. Unlike Events, however, these methods will be called as soon as the channel is notified, in the order that they were subscribed.
publisher.add( function( _message ) {
show_debug_message( _message );
}
publisher.notify( "Hello World!" );
Here we will display the message, "Hello World!" when the channel is notified. This is helpful for small closed systems you want to pass messages through. Note the argument provided to notify will be passed to the method that subscribed to the channel. Remember that methods are bound at the scope that they were created at, and thus a single instance can be in many channels, or even the same channel multiple times. Additionally, like Events, any objects that no longer need to listen to a channel should be cleaned up afterwards to avoid an unexpected crash.
However, we've looked at PublisherChannel so far. A Publisher is a manager for a number of channels, which can represent an entire ecosystem of channels. One common use might be for something like an achievement system:
global.achievements = new Publisher()
global.achievement.subscriber_add( "kills", function( _number ) {
global.kills_progress += _number;
if ( global.kills_progress > 1000 ) {
steam_set_achievement("kills1000");
}
});
global.achivements.channel_notify( "kills", 1 );
In this case anything that notifies the "kills" channel will cause the number to be incremented and unlock the achievement when needed. However, the value of the publisher-subscriber model is anyone can listen to this "kills" channel. Perhaps another subscriber listens to this channel a places the kill into a death ticker, or checks to see if a kill combo has been achieved. The point of a publisher-subscriber system is that different objects can listen for messages on things they should hear about. Rather than dumping all of this code into the place where something dies, you simply notify the publisher and it will pass on the message to any subscribers.
Logs are boring, but they can be a huge help when troubleshooting and debugging your game. Once you ship your game this becomes especially true as they may be one of the best places to get feedback about something that went wrong. FAST tries to make this process simply by making writing to multiple outputs simple, as well as providing a handy framework to separate what you want to log. Creating a new Logger is quite simple:
logger = new Logger( "debug", 144, System, new FileText( "log/debug.txt", false, true );
logger.write( "Howdy Planet!" )
We're done. System is a special output that writes to the GMS IDE output window. Now when you call write(), it will be written to the Output window and to
log/debug.txt`. It is possible to write your own outputs as well, so if you want to write to a network or an Arduino board, or wherever you think your logging needs to go, it's easy to do and will work seamlessly.
Files are a part of GMS that can be unexpectedly annoying to deal with. FAST makes it easy to write your own file types while providing convenience features when dealing with them, for example:
var _text = new FileText( "log/debug.txt", true, false );
name = _text.read();
Here we open log/debug.txt
if it exists and read it into FileText. You can then read from and write to the file the same as you would anything else, and you can even insert lines or return to the beginning if needed. When you are done, simply call close()
and your changes will be saved to disk, or discard()
and they'll be ignored. You can also set the file to be read only which will protect against writing to or saving the file. FAST contains a few basic file types and more are added periodically. If there's a file type you'd like to see added, open an Issue and let me know!
Name | Type | Value | Description |
---|---|---|---|
FAST | func | ( FASTManager() ) | Wrapper |
__FAST_version | string | "3.3h" | The current FAST revision |
__FAST_date | string | "10/09/2020" | The last revision date |
syslog | func | ( SystemOutput() ).write | Virtual function |
System | func | ( SystemOutput() ) | Wrapper |
FAST_LOGGER_DEFAULT_LENGTH | int | 144 | The default logger string length |
FAST_DISABLE_EVENTS | bool | false | If set to true __FASTtool will not be instantiated |
DEBUGGER_ENABLE | bool | false | Enables debugging in FAST modules |
ERROR_LEVEL | int | 4 | The error level the debuggers should respond to |
ERROR_CRITICAL | int | 1 | Highest level |
ERROR_NONFATAL | int | 2 | Moderate level |
ERROR_NOTIFY | int | 3 | Low level |
ERROR_DEBUG | int | 4 | Debugging only |
Devon Mullane 2020