Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The DelegateInstruction provides a quick way to call methods at a future time. The DelegateInstruction is similar in function to the MethodInstruction class; however, it has a simpler interface and can be easier to use for no-argument or one-argument methods. Note that the AddSafe method can be used to call delegate instructions on the primary thread: http://flatredball.com/documentation/api/flatredball/flatredball-instructions/flatredball-instructions-instructionmanager/flatredball-instructions-instructionmanager-addsafe/
The DelegateInstruction constructor can take a 0-argument and 1-argument method. In the case of the 1-argument, you must pass an object to be passed as the argument. The following code shows how to call Emit on an Emitter in 2 seconds:
The DelegateInstruction method can be used to call any method (as long as it has the proper number of arguments). The following code shows how to destroy an object after a 1-second delay when the user presses the space button.
Lambda expressions can be used with delegate instructions. For example, the following shows how to create a delegate instruction which sets an object's X to 5.
The "Call" function is a function which can be used to delay the execution of code. The Call function is conceptually similar to the Set function, but it is more flexible, allowing you to use lambda expressions, anonymous delegates, and regular functions. The Call function is a great way to perform delayed actions and "scripting". Internally the Call function creates a DelegateInstruction and adds it to the calling IInstructable. Most IInstructable implementations, such as Sprites, shapes, and Entities have automatic code to execute their instructions. Therefore, simply calling the Call.After methods will result in these objects performing the desired action at the given time. Custom implementations of IInstructable need to call their own instructions every-frame for instructions added through Call.
Note: This is an extension method. To use this, you will need to add:
The following code shows how to call Emit on an Emitter after 2 seconds:
Since all Entities are IInstructables, you can also call custom methods on Emitters as follows:
Entities can even destroy themselves after a certain amount of time:
You can also use lambda expressions inside Call:
Lambdas can be used to call methods which require parameters:
You can use larger lambda statements:
Screens are also IInstructables meaning you can use the Call function on Screens:
Call can be used to cascade actions. For example, consider an Entity which has a number of things which need to happen when it dies. The "Die" function may look like this:
Note that the functions used in the Call function are omitted to keep the example short. This example assumes that FlashRed, PlayDieSound, and StartFadingOut are functions with no parameters, and that they are defined in the same class as PerformDieActions. Destroy is defined for you by Glue in every Entity.
Entities and Screens both implement IInstructable automatically, meaning you don't have to do any modification to your code to be able to use the Call function. Keep in mind that since the Call function is an "extension method", you will need to use the "this" prefix to have access to the Call function if you intend to use Call on a Screen/Entity inside of its own custom code.
The Call function is a shorthand way to call a function through instructions. The Call function itself doesn't introduce any new functionality that isn't already available to the IInstructable interface; it just simplifies the syntax. Therefore, when you use the Call method, internally this creates an instruction. This can be verified:
The simplest scenario for using Call is within an IInstructable-implementing object (such as an Entity). For example:
In this case, the object containing the code (this) will hold the instruction, and the Destroy function will be called on "this" as well. However, you can call code that belongs to other objects. For example, if you have a list of Entities which should be destroyed in one second:
In this case, the objectAtI is both the object that will contain the instruction, and it will also be the object that will be destroyed. If possible, it is recommended that the object that owns the function passed to Call should also be the object that is performing the call. In other words:
Of course, this may not always be possible. For example, an Entity may contain an object which is not IInstructable. In that case, the Entity should "own" the instructions. In other words, this is okay:
Instructions are objects which store a value that will be set to a particular property at a given time. In other words, Instructions can be used to do something at some fixed time in the future.
These are useful for creating cut scenes and performing predictable behavior without explicitly holding on to references to update objects every frame.
Instructions can be used to:
Set fields or properties
Call methods
Perform any custom code that you write
FlatRedBall objects which implement the IInstructable interface are designed to store and execute instructions - as long as they belong to a manager which performs this behavior automatically. However, Instructions can operate on any object - not just IInstructables.
For more information, see the IInstructable wiki entry.
In most cases simply creating a new instance of an instruction and adding it to a managed IInstructable like a Sprite or PositionedModel is all that's needed. The engine will handle executing the instruction then cleaning it up afterwards. But if you're looking to work more with instructions you might be asking how instructions are executed and where what happens to them after execution.
As far as implementation in the FlatRedBall Engine, Instructions can exist in one of two locations:
Inside a IInstructable
Inside the InstructionManager
The best place to put an instruction is in an IInstructable's Instructions property. If this IInstructable is managed by the engine, then you don't have to worry about doing anything to execute or remove the Instructions. It all happens automatically.
Another benefit of putting an Instruction in an IInstructable is that "ownership" of instructions is defined. This will make more sense when we discuss the second option of putting Instructions in the InstructionManager.
If you are dealing with an object which is not an IInstructable (such as Screens, then you can use the InstructionManager to store and execute your instructions appropriately. The InstructionManager exposes a property called Instructions which holds and can execute instructions. While this is convenient, we don't recommend putting Instructions in this list if they can be added to an IInstructable. The reason for this is the InstructionManager only exposes one list, so if you have multiple objects which use Instructions, all of their Instructions will be mixed into the same list. This can make management and debugging more difficult.
To understand how to manually work with Instructions, the first thing to keep in mind is that Instructions only do whatever is in their Execute method. For example, the following code creates an instruction that will set the X of the given PositionedObject to 5 in 10 seconds:
At this point, the Instruction can manually be executed, and it can be done so multiple times over and over:
So, the question is then - how do you destroy an Instruction? Well, you actually don't have to do anything - unless of course you've written a custom Instruction that requires cleanup.
In other words, simply let the object fall out of scope, or remove it from the list(s) that it belongs to, and it'll be gone.
Of course, if you want to test time, you can compare the TimeManager's CurrentTime to the Instruction's TimeToExecute:
The InstructionList is a class designed especially to handle lists of Instructions and it provides a number of methods which can simplify manual management of Instructions. For more information, see the InstructionList entry.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The IInstructable interface specifies that an object can store instructions in an InstructionList. Most FlatRedBall classes which implement the IInstructable interface have managers which handle Instruction execution. Instructions allow the setting of properties at a predetermined time in the future without any explicit management.
The FlatRedBall Engine provides a generic Instruction which can be used to set any property. The following code moves a Sprite in a square when the space bar is pushed.
Instructions must be called on the object that will be modified. You cannot use the "dot" operator to set properties of embedded items. For example, the following is not valid:
Instead you should pass the instance as the first argument and have the property as the second argument:
The InstructionManager provides methods for performing common behavior on different objects. See the InstructionManager wiki entry for more information.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The Set method is an extension method for IInstructables which simplifies the creation of property and field setting instructions. Using the Set method enables the creation of instructions which will automatically be added to the calling IInstructable's InstructionList.
Note: This is an extension method. To use this, you will need to add:
The following code can be used to change a Sprite's X value to 4 after 1 second:
Since all Entities in Glue are also IInstructables, then any public property can be set on an Entity through reflection:
Note: Instructions should only set public fields and properties. The reason for this is because some platforms (such as Windows Phone) only allow the setting of public properties.
The Instructions member in an IInstructable represents all of the instructions which have been created and added to the IInstructable. Instructions can be added to the InstructionList a number of ways:
Through a direct add, such as by calling:
Through InstructionManager helper methods, such as by calling:
Through the "fluent instruction" for instructions, such as by calling:
Instructions.Clear will remove all instructions which are held by an object. Clear can be used to cancel any existing instructions. For example, the following code will set an IInstructable to move to the X value ater 3 seconds, but then cancel that instruction and move it instead after 2 seconds.
The InstructionManager is a class that provides methods for performing common tasks with instructions.
See the tile based movement tutorial.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The Add method adds the argument instruction to the InstructionManager. The InstructionManager stores stores its own list of instructions which are executed according to their TimeToExecute.
For more information on how the InstructionManager handles instructions that are added to it, see the InstructionManager.Instructions page.
The Instructions property is an exposed InstructionList which the InstructionManager will check and execute if according to the TimeManager's CurrentTime property. Instructions which do not necessarily belong to an instance, or which are to be executed on an object which does not implement the IInstructable interface can be added to the InstructionManager's Instructions property for automatic execution.
Instructions can be directly added or removed from the InstructionManager.Instructions list:
The InstructionManager will execute Instructions if the InstructionManager's IsExecutingInstructions property is true (default). The InstructionManager will automatically check the time of instructions and execute them.
Instructions are a common part of the FlatRedBall game engine, and many FlatRedBall objects implement the IInstructable interface. If an instruction is instantiated which should operate on an IInstructable, then the instruction should be added to the IInstructable's Instructions property. This suggests that the IInstructable "owns" the instructions which will operate on it. Having each IInstructable contain Instructions which will operate on it can help improve debugging. Some objects, such as Screens do not implement the IInstructable interface, or are not automatically managed by a manager. It is common practice to place Instructions which will operate on these objects in the InstructionManager's Instructions list. Instructions in this list will also automatically be executed, and provide a centralized, easy to use list for instructions. However, in general, use the Instructions property for individual objects if available before using the InstructionManager's Instructions list.
You can clear all instructions by simply calling the Clear method on the Instructions object:
The InstructionList class is a class which provides methods that can simplify manual interaction with Instructions. Most of the time you will not need to manually interact with Instructions as the FlatRedBall Engine provides automatic management for Instructions, but more sophisticated applications which need more direct access to Instructions will benefit from the use of the InstructionList class.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The MoveTo function is a function which will take the argument PositionedObject and will set its Velocity so that it moves to the argument location in a set amount of time, as specified by the secondsToTake parameter. The MoveTo function will do two things:
It will modify the velocity values of the PositionedObject.
It will add instructions to the PositionedObject's Instructions list.
The MoveToAccurate creates a set of Instructions for moving a PositionedObject to a given point in a set amount of time.
The following code moves a Sprite to the position where the user clicks the Mouse. Note that this could be implemented with any PositionedObject, including any Glue entity. Add the following using statements to your Glue screen:
Add the following to your screen's CustomInitialize to show the mouse:
Add the following to your Screen's CustomActivity, assuming SpriteInstance is a Sprite in your Screen:
The AddSafe method is a thread-safe way to add instructions to the engine. Typically "add" calls cannot be made on managers; however, the AddSafe method allows adding instructions from any thread.
The AddSafe method takes an Instruction argument. The following code shows how to call AddSafe assuming you have a valid Instruction.
The AddSafe method can be called with an action to execute. This makes calling code on the primary thread easy:
As mentioned above, objects cannot be added to managers on secondary threads. The following shows how to add a Sprite on the primary thread
Code may execute next frame
Since the InstructionManager only performs instruction execution one time per frame, your code may execute after instructions have been processed that frame. This means that your code may not execute until next frame.
ObjectsIgnoringPausing contains a list of objects which do not implement PositionedObject which should be ignored in pausing. Objects which do implement PositionedObject should not be added to this list unless they have additional pausing behavior which is checked by external systems. In a default FlatRedBall project this is not the case.
For code examples on how to use ObjectsIgnoringPausing in combination with pausing your game using PauseThisScreen, see the Screen.PauseThisScreen page.
This method creates instructions for moving the argument PositionedObject through a list of points which is created from the list of IPositionables passed as the second argument. This method can be used in combination with the NodeNetwork class to automatically move objects along a path.
The following creates five Sprites. The four in the corners represent points that the fifth will move through. Add the following using statements:
Add the following to Initialize after initializing FlatRedBall:
PropertyCollections are a method of encapsulating a group of property values. Using PropertyCollections can simplify and make code more readable.
The following example creates a Sprite and sets its properties through a PropertyCollection.
Unlike assigning properties using regular code the values assigned to properties through PropertyCollections must match the type exactly. For example the following code is acceptable:
The value of 3 is an integer value, as opposed to 3.0f, but the compiler casts the value to a float without any problem. However, the following code would result in a crash:
Instead, XVelocity must be explicitly given a float:
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The LateBinder class is a class which provides efficient, standardized access to properties and fields through reflection. In other words, the LateBinder can be used to get and set values on objects using their string names. The LateBinder is very effective when writing tools and performing high-level actions on objects.
The following code sets the X, Y, and Z properties of a Sprite using the LateBinder:
Add the following using statements:
Assuming mSprite is a valid Sprite:
If you are familiar with .NET then you may already be comfortable using the built-in methods for getting and setting values for reflection. Syntactically, the LateBinder may not appear to provide much in the way of convenience:
The LateBinder is most effective in situations where a particular property must be read or set multiple times. It caches off the getters and setters for properties and uses these delegates to invoke the properties on any subsequent calls, making it very fast. Keep in mind that the LateBinder does quite a bit of work internally when a property is read or set for the very first time. Therefore, if you measure the speed of the LateBinder when first calling GetValue or SetValue, you will notice a significant cost in speed. However subsequent calls usually take about 10% of the amount of time as using the raw reflection calls.
Also, using the LateBinder is also effective for performing reflection in a cross-platform manner. The LateBinder will attempt to cache off delegates if possible, but it will fall back to regular reflection calls on platforms which don't support the faster method (such as the 360).
The LateBinder provides efficient reflection because it dynamically creates instances for given types of objects and also dynamically retrieves their getters and setters for arguments when GetProperty and SetProperty are called. The initial instantiation and retrieval is slow compared to even raw reflection calls. If you are particularly sensitive to performance, you may want to consider calling GetProperty or SetProperty (depending on what you will be using) for each property you plan on setting in your Screen's Initialize (or CustomInitialize if using Glue) method. This will get the slower instantiation out of the way so the LateBinder will be very efficient every time you use it.
The GetValue method allows you to get the value of a variable using reflection by passing in a string. For example, you could get the X value form a Sprite by either hard-coding the value or by using the latebinder:
The RotateToAccurate method creates and adds for rotating the argument PositionedObject to the argument rotation. The method takes three values as it can perform rotation on the X, Y, and Z rotation components.
The following code creates and rotates a so that its rotation matches the angle from the to the when the user clicks the left button. Add the following using statements:
Add the following at class scope:
Add the following in Initialize after initializing FlatRedBall:
Add the following in Update:
Note - StaticMethodInstruction is now marked as obsolete in favor of using and .
StaticMethodInstructions can be used to call methods belonging to static classes. This class is useful for calling methods belonging to FlatRedBall manager classes like the .
The following code creates an instruction that will add a Sprite to the scene after 2 seconds. can be added to the to be executed automatically. Add the following using statements:
Add the following to Initialize after initializing FlatRedBall:
The ExecuteAndRemoveOrCyclePassedInstructions will execute instructions which should be executed based off of the current time, then either remove or cycle any executed instructions. This method allows manual execution of without requiring the user to write the logic of time testing and cycling.
This method is used internally by the FlatRedBall Engine so calling it will guarantee behavior which matches the engine's behavior regarding management.
Assuming that instructionList is a valid instance, the following code can be called every frame to execute and remove from the instructionList:
Did this article leave any questions unanswered? Post any question in our for a rapid response.
Did this article leave any questions unanswered? Post any question in our for a rapid response.
The Pulse method creates a recurring set of instructions used to change the argument IScalable's Scale and Scale Velocity. The result is a pulsing effect.
The following creates a Sprite which pulses using a set of defined parameters.
Add the following using statements:
Add the following to Initialize after initializing FlatRedBall;
MethodInstructions are a way of calling a method at some time in the future. They can simplify the creation of effects and animation in game development. The DelegateInstruction provides the same functionality for simple cases.
There are a few things to remember when using MethodInstructions:
While MethodInstructions can be manually executed, the easiest way to use them is to add them to an IInstructable that is being managed such as a Sprite. This way you don't have to manually watch for instructions to call them. The manager takes care of it for you!
MethodInstructions cannot call static methods. You'll see in the following example that SpriteManager.RemoveSprite needs to be wrapped in another method. Another alternative is to create a StaticMethodInstruction.
The following code creates an effect that could be used for explosions when the user presses the space bar. The code does the following things:
These instructions are added to the InstructionManager since there is no object around to "own" these Instructions.
When a Sprite is created its properties are set and another MethodInstruction is created to remove the Sprite after 1 second.
Add the following using statement:
Add the following code to Update:
Add the two methods which will be used as MethodInstructions:
The third argument to the MethodInstruction constructor is an argument list. This argument list is an object array (object[]) which stores the arguments.
For example, if you were calling a function called SetSpriteScaleAtTime which had the following signature:
You may create an argument list as follows:
MethodInstructions attempt to call methods using reflection. They obtain the method to call using the name of the method. However, if the method that you want to call has multiple overloads then you will need to supply a MethodInfo to tell which version of the method you want to call.
For example, let's say you are working with an AxisAlignedRectangle instance and you want to call CollideAgainst using a MethodInstruction. The following code can be used to call CollideAgainst against a Circle:
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The PauseEngine method can be used to freeze all velocity, rate, and acceleration, properties as well as delay all Instructions that belong to objects managed by engine managers. Calling PauseEngine and UnpauseEngine will temporarily stop then resume nearly all behavior for objects which are managed by the FlatRedBall, and in many cases is all that is necessary to implement pause functionality.
The PauseEngine method is used by the PauseThisScreen method in the Screen class.
Keep in mind that calling PauseEngine does NOT stop the management of objects by the engine. In other words, if an object with a non-zero velocity is stopped by calling PauseEngine, but its velocity is then set to a non-zero value before calling UnpauseEngine, the object will resume movement.
This allows select objects to continue managed behavior despite other objects being paused. For example, pausing may freeze the behavior of all objects except a pause menu which should continue to behave as normally. Once the game is unpaused and the pause menu is removed, calling UnpauseEngine resumes the behavior of all objects.
Also keep in mind that any behavior which is not dependent on properties managed by the engine or dependent on Instructions must be manually controlled when implementing Pausing functionality.
The following code creates an Emitter which emits Sprites. The sprites have velocity, rate, and acceleration methods set. Despite the complex behavior of the Sprites, a simple call to PauseEngine stops all behavior. Similarly, calling UnpauseEngine resumes all behavior as expected.
Notice that the TimedEmit is a method which is explicitly called in the Update method. Since it is not managed by the engine, it must manually be called only when the program is not stopped.
Add the following using statements:
Add the following at class scope:
Add the following in Initialize after initializing FlatRedBall:
Add the following in Update:
Define the BounceAgainstEdges CustomBehavior at class scope:
The PauseEngine method was written to work well with Screens. The PauseEngine does not turn off engine management - this is done so that any menu that appears while paused (allowing the user to restart or unpause) will still have its usual updates called. Therefore, the order for pausing and unpausing should be as follows:
Call PauseEngine
Add the Popup Screen
<User Unpauses>
Remove the Pause Screen
Call UnpauseEngine
The removal of the PauseEngine and calling of UnpauseEngine does not necessarily have to be performed in this order, but it is conceptually clean to treat these events as a stack and "remove off of the top".