Advertisement
RedKnight91

GMS Event Framework

Apr 10th, 2020
1,834
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.     GMS2 Event Framework
  2.    
  3.     Purpose:
  4.         To implement Event-driven Architecture in Game Maker
  5.    
  6.    
  7.     Details:
  8.         Event-driven Architecture is perfect for ensuring that:
  9.             - Events (significant changes in program state) are checked for
  10.               only once (as opposed to multiple times from different instances)
  11.              
  12.             - Single Responsibility Principle can be applied, avoiding performance of several
  13.               non-related tasks in a single object.
  14.              
  15.         Using events ensures that an instance (emitter) emits an event, and all responsible instances (listeners)
  16.         are alerted so they can perform their tasks for that event occurrence.
  17.    
  18.    
  19.     How it works:
  20.         0. Create an instance of EventManager (persistent) in your first room
  21.            (I do this in an initialization room)
  22.        
  23.         1. Set up Event Types in an enum (initEventTypes script)
  24.            for any kind of event you might be interested into
  25.        
  26.         2. Instruct instances (listeners) to listen for occurrences of an Event Type (e.g. a mouse click),
  27.            specifying a callback script for the event
  28.        
  29.         3. Make instances (emitters) emit events of a specific type, passing event-related data as args
  30.            (e.g. clicked mouse button, mouse coordinates)
  31.            
  32.         4. The EventManager triggers the callback for all listeners for that event
  33.        
  34.    
  35.     Usage Example:
  36.         //initEventTypes script
  37.             EventTypes { MOUSE_CLICK, KEY_PRESS, GAME_WIN, SCORE_REACH_9000, SIZE }
  38.        
  39.         //Your object's create code
  40.             subscribe(EventTypes.SCORE_REACH_9000, callbackOver9000)
  41.        
  42.         //From the instance responsible for score tracking
  43.             if (score > 9000) emitEvent(EventTypes.SCORE_REACH_9000, score)
  44.  
  45.         //Script callbackOver9000(eventArgs)
  46.             var score = argument0
  47.             show_message_async("IT'S OVER 9000!!! Your score is: " + string(score))
  48.            
  49.         //Your object's step code
  50.             //Stop listening for events of this type
  51.             unsubscribe(EventTypes.SCORE_REACH_9000)
  52.    
  53.    
  54.     Listener scripts:  
  55.         //Listen for event type emitted from any instance
  56.         subscribe(eventType, callback)
  57.  
  58.         //Listen to event type emitted from specific instances
  59.         subscribeToInstance(eventType, target, callback)                                //Pass an instance ID
  60.         subscribeToInstanceByVar(eventType, "target", callback)                     //Pass the name of a variable which contains an instance ID
  61.         subscribeToInstancesByList(eventType, targetList, callback)                     //Pass a list of instance IDs
  62.         subscribeToInstancesByKeyMap(eventType, targetMapKeys, callback)                //Pass a map of instance IDs (keys)
  63.         subscribeToInstancesByValueMap(eventType, targetMapValues, callback)            //Pass a map of instance IDs (values)
  64.  
  65.         //Listen to event type emitted from specific objects
  66.         subscribeToObject(eventType, targetObj, true, callback)                     //Pass an object index
  67.         subscribeToObjectByVar(eventType, "targetObj", true, callback)                  //Pass the name of a variable which contains an object index
  68.         subscribeToObjectsByList(eventType, targetObjList, true, callback)              //Pass a list of object indices
  69.         subscribeToObjectsByKeyMap(eventType, targetObjMapKeys, true, callback)     //Pass a map of object indices (keys)
  70.         subscribeToObjectsByValueMap(eventType, targetObjMapValues, true, callback) //Pass a map of object indices (values)
  71.        
  72.     Stop Listener scripts:
  73.         //Stop the current instance from listening to all events or a specific type
  74.         unsubscribeFromAll()
  75.         unsubscribe(eventType)
  76.        
  77.         //Stop the current instance from listening to an event type
  78.         //From a specific instance / instances
  79.         unsubscribeFromInstance(eventType, target)                                  //Pass an instance ID
  80.         unsubscribeFromInstanceByVar(eventType, "target")                           //Pass the name of a variable which contains an instance ID
  81.         unsubscribeFromInstancesByList(eventType, targetList)                       //Pass a list of instance IDs
  82.         unsubscribeFromInstancesByKeyMap(eventType, targetMap)                      //Pass a map of instance IDs (keys)
  83.         unsubscribeFromInstancesByValueMap(eventType, targetMap)                    //Pass a map of instance IDs (values)
  84.                                                                                
  85.         unsubscribeFromObject(eventType, targetObj)                                 //Pass an object index
  86.         unsubscribeFromObjectByVar(eventType, "targetObj")                          //Pass the name of a variable which contains an object index
  87.         unsubscribeFromObjectsByList(eventType, targetObjList)                      //Pass a list of object indices
  88.         unsubscribeFromObjectsByKeyMap(eventType, targetObjMap)                     //Pass a map of object indices (keys)
  89.         unsubscribeFromObjectsByValueMap(eventType, targetObjMap)                   //Pass a map of object indices (values)
  90.        
  91.     Listening to Vars/Lists/Maps:
  92.         - subscribeToInstanceByVar/subscribeToObjectByVar
  93.             Require the name of a variable (e.g. "target") containing an instance ID / object index.
  94.             If you update the var to another ID / object index, the listener will update automatically.
  95.            
  96.         - subscribeToInstancesByList/subscribeToObjectsByList
  97.             Require a list containing instance IDs / object indices
  98.            
  99.         - subscribeToInstancesByKeyMap/subscribeToObjectsByKeyMap
  100.             Require a map where the map KEYS are instance IDs / object indices
  101.            
  102.         - subscribeToInstancesByValueMap/subscribeToObjectsByValueMap
  103.             Require a map where the map VALUES are instance IDs / object indices
  104.    
  105.     Important info:
  106.         - You can add Event Types as you go, they don't need to all be added at the start of development
  107.        
  108.         - Use the right unsubscribe script (should be the same as your subscribe() script),
  109.           if you use an incorrect unsubscribe script the subscription won't be deleted and the object will keep listening
  110.          
  111.           Example:
  112.             subscribeToInstancesByList(eventType, myList, callback)
  113.             stopListengInstanceList(eventType, myList)
  114.  
  115.        
  116.         - Destroyed listener instances are automatically cleaned up from the EventManager periodically
  117.        
  118.         - Callbacks are performed within listener scope ( with(listener) )
  119.            
  120.         - Callbacks now receive event data as regular arguments, for example:
  121.             emitEvent(EventTypes.MOUSE_CLICK, mouse_button, mouse_x, mouse_y)
  122.            
  123.             //Callback script
  124.             var mouseButton = argument0
  125.             var mouseX = argument1
  126.             var mouseY = argument2
  127.        
  128.         IMPORTANT: It is up to you to know what data you're returning when emitting the event using emitEvent(type, arg, arg, ...)
  129.         You have to ensure the script you're using will either:
  130.             - Use variable arguments (e.g. argument[0], argument[1])
  131.             - Use the correct number of arguments as passed by emitEvent
  132.         Any other behavior will result in a crash
  133.    
  134.    
  135.    
  136.     Updates:
  137.         - Replaced Event object with ds_map
  138.         - Added possibility to listen to events emitted from specific instance/object, from lists and maps of instances/objects
  139.         - Replaced Event Data array which argument list for more natural callback handling
  140.    
  141.     Future updates (pending stable Game Maker 2.3 update):
  142.         - Possibility to use anonymous function callbacks instead of scripts
  143.        
  144.    
  145.     Contacts:
  146.         mikecazzarolli@gmail.com
  147.         twitter.com/mikecazzarolli
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement