The Gang of Four describe the command pattern as "Encapsulate a request as an object, thereby letting users parameterise clients with different request, queue or log requests, and supports undoable operations."Another way to describe it as a thingified method call, which means to wrap a method call in a function.
The command pattern is very similar to callbacks, first-class functions, function pointers and partially applied functions. The Gang of Four also describle commands as an object oriented replacement for callbacks.
An example use for the command pattern is configurable/remappable input, what this means the user can change what actions a button/bumper/trigger can do. Usually specific actions are mapped to specific input like so:
void InputHandling()
{
if (Input.GetButtonDown(BUTTON_X))
{
Reload();
}
else if(Input.GetButtonDown(BUTTON_Y))
{
SwapWeapons();
}
else if(Input.GetButtonDown(BUTTON_B))
{
Melee();
}
else if(Input.GetButtonDown(BUTTON_A))
{
Jump();
}
}
We could set up preset functions that contain different variations of the type of input and corresponding actions. However, that might not be flexible enough and so allowing the players to swap out actions is a better alternative, which is where commands come in. We can use pointers for each button and when the player wants to change that buttons input we simply point to a new command object.
Example Code
Command Class
class Command
{
public:
virtual ~Command() { };
virtual void Execute() = 0;
};
Example Command Classes
class JumpCommand : public Command
{
public:
virtual void Execute() { Jump(); }
};
class MeleeCommand : public Command
{
public:
virtual void Execute() { Melee(); }
};
class SwapWeaponsCommand : public Command
{
public:
virtual void Execute() { SwapWeapons(); }
};
Input Handler
class InputHandler
{
public:
void HandleInput();
// Methods to bind commands
private:
Command* buttonA;
Command* buttonB;
Command* buttonX;
Command* buttonY;
};
void HandleInput()
{
if (Input.GetButtonDown(BUTTON_X))
{
buttonX->Execute();
}
else if(Input.GetButtonDown(BUTTON_Y))
{
buttonY->Execute();
}
else if(Input.GetButtonDown(BUTTON_B))
{
buttonB->Execute();
}
else if(Input.GetButtonDown(BUTTON_A))
{
buttonA->Execute();
}
}
However, this assumes that whatever functions that are wrapped in the execute functions as part of the command class, can find the player to do whatever action is required. This isn't always the case and so we can modify the code so that we pass in a reference to an object and then call a specific function of that object. This means we now make these changes to the code:
class Command
{
public:
virtual ~Command() { }
virtual void Execute(Actor& actor) = 0;
};
class SwapWeaponsCommand : public Command
{
public:
virtual void Execute(Actor& actor)
{
actor.SwapWeapons();
}
};
Command* HandleInput()
{
if (Input.GetButtonDown(BUTTON_X))
{
return buttonX;
}
if(Input.GetButtonDown(BUTTON_Y))
{
return buttonY;
}
if(Input.GetButtonDown(BUTTON_B))
{
return buttonB;
}
if(Input.GetButtonDown(BUTTON_A))
{
return buttonA;
}
return NULL:
}
You will notice that we now return the commands, this is because we don't know the actor to execute functions from and so once we know the command, we can pass in the reference to the actor, to the command. Like so:
Command* command = HandleInput();
if (command)
{
command->execute(actor);
}
This also means we can actually control any actor within the game, as we can just swap out which actor is passed in to the execute function.
Thursday, January 24, 2019
Number Systems: Introductions
Number systems allow us to count various things with a lot more ease than before. The most common one is Decimal or Base 10, this is most likely because humans generally have 10 fingers, 5 on both hands.
Base 10
Base 10 uses 10 symbols: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
This combined with places allows us to use large numbers such as 231.
If we split 231 down we get:
- 2 x 100s
- 3 x 10s
- 1 x 1s
It is interesting to note that each place increases a multiple of 10, but also can be explained exponentially so:
- 1 = x10^0
- 10 = x10^1
- 100 = x10^2
- 1000 = x10^3
Base 2 - Binary
Base 2 uses 2 symbols: 0, 1
These usually represents on and off or true and false.
Instead of each place being represented by x10^n, base 2 places are represented by x2^n.
So the first 8 places of binary are:
- 1 = x2^0
- 2 = x2^1
- 4 = x2^2
- 8 = x2^3
- 16 = x2^4
- 32 = x2^5
- 64 = x2^6
- 128 = x2^7
We can now convert 231 base 10 into base 2
128 64 32 16 8 4 2 1
---------------------------
1 1 1 0 0 1 1 1
So in binary 231 is represented as 11100111 and we can check this by adding each place that has a value of 1: 128 + 64 + 32 + 4 + 2 + 1 = 231
Base 16 - Hexadecimal
Base 16 uses 16 symbols: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A (10), B(11), C(12), D(13), E(14), F (15)
As with base 2, base 16 places are represented by something different to x10^n. The places are represented by x16^n. So the first 4 places of base 16 are:
- 1 = x16^0
- 16 = x16^1
- 256 = x16^2
- 4096 = x16^3
We can now figure out how to write 231 in base 16
4096 256 16 1
-------------------
E 7
So in base 16, 231 can be represented as E7 and we can check this by adding the each places total together.
E or 14 x 16 = 224
7 x 1 = 7.
224 + 7 = 231
Sample Problem: C++ - Order of Execution of Constructors & Destructors Between a Parent & Child Class
You have a parent class that has a constructor and a non-virtual destructor, as well as a child class that inherits from the parent class. What is the execution order for the constructors and destructors?
- Parent constructor is called
- Child constructor is called
- Child destructor is called
- Parent destructor is called
Source Code
Source.cpp
#include "Parent.h"
#include "Child.h"
#include <iostream>
int main()
{
Child* testChild = new Child();
testChild->~Child();
int endInput;
std::cin >> endInput;
return 0;
}
Parent.h
#pragma once
#include <iostream>
class Parent
{
public:
Parent();
~Parent();
};
Parent.cpp
#include "Parent.h"
Parent::Parent()
{
std::cout << "Parent Constructor Called" << std::endl;
}
Parent::~Parent()
{
std::cout << "Parent Destructor Called" << std::endl;
}
Child.h
#pragma once
#include "Parent.h"
#include <iostream>
class Child : Parent
{
public:
Child();
~Child();
};
Child.cpp
#include "Child.h"
Child::Child()
{
std::cout << "Child Constructor Called" << std::endl;
}
Child::~Child()
{
std::cout << "Child Destructor Called" << std::endl;
}
Console Output
Wednesday, January 23, 2019
Matrices Pt 2
If you haven't read part one, it might be a good idea as it goes over the basics of matrices.
Multiplication
You can think of calculating the matrices multiplication by thinking in terms of vectors and dot products, For example, you have matrix A and matrix B, both are a 2x2 matrix, you want to multiply the two together to get matrix C. The top left value of matrix C is equal to the dot product of the first row of matrix A and the first column of matrix B. Then to get the top right value of matrix C, you do the same but using the second column of matrix B. The bottom two values of matrix C can be calculated in the same before but using the second row of matrix A.
Of course this scales upwards so if you have two 4x4 matrices, the working out is still the same as before. Multiplication doesn't require both matrices to have the same dimensions, although it does require the number of columns in matrix A to be the same as the number of rows in matrix B.
It should be noted that matrix multiplication is note commutative, however, it is both associative and distributive over addition. Also if a matrix is multiplied by the identity matrix then the matrix stays the same. You can also calculate the identity matrix by multiplying a matrix by its inverse.
Matrix Multiplication Properties
Multiplication
You can think of calculating the matrices multiplication by thinking in terms of vectors and dot products, For example, you have matrix A and matrix B, both are a 2x2 matrix, you want to multiply the two together to get matrix C. The top left value of matrix C is equal to the dot product of the first row of matrix A and the first column of matrix B. Then to get the top right value of matrix C, you do the same but using the second column of matrix B. The bottom two values of matrix C can be calculated in the same before but using the second row of matrix A.
Of course this scales upwards so if you have two 4x4 matrices, the working out is still the same as before. Multiplication doesn't require both matrices to have the same dimensions, although it does require the number of columns in matrix A to be the same as the number of rows in matrix B.
It should be noted that matrix multiplication is note commutative, however, it is both associative and distributive over addition. Also if a matrix is multiplied by the identity matrix then the matrix stays the same. You can also calculate the identity matrix by multiplying a matrix by its inverse.
Matrix Multiplication Properties
- A * B ≠ B * A - This means that it isn't communative
- A * (B + C) = A * B + A * C - This means that it is distributive
- A * (B * C) = C * (A * B) - This means that it is associative
- A = A * I
- I = A * A^-1
Matrix Multiplication Dimension
The dimensions of the end matrix of a matrix multiplication are the number of rows in the first matrix and the number of columns in the second matrix. So if we had a 3x2 matrix and a 2x5 matrix, the dimension of the final matrix is 3x5.
The dimensions of the end matrix of a matrix multiplication are the number of rows in the first matrix and the number of columns in the second matrix. So if we had a 3x2 matrix and a 2x5 matrix, the dimension of the final matrix is 3x5.
Transpose
When transposing a matrix, you convert each row of the matrix to its corresponding column, so the first row becomes the first column,etc. Transposing is denoted by a T.
Transforming 3D Vectors by Matrices
So you need to transform a vector by a specific matrix, well the first thing is to convert the vector into a matrix. There are two ways to do this, row major and column major.
For example, Vector A = {1, 2, 3} can either look like:
![]() |
| Row Major Version |
![]() |
| Column Major Version |
Depending on the kind of matrix you are multiplying by it makes sense to convert to that type of major. So if a matrix is intended to be multiplied by a row major matrix then convert it to that type of major. However, if that is not possible you can transpose the multiplaction matrix to multiply with the opposite major type.
x^1 = x * a + y * b + z * c
y^1 = x * d + y * e + z * f
z^1 = x * g + y * h + z * i
x^1 = a * x + b * y + c *z
y^1 = d * x + e * y + f * z
z^1 = g * x + h * y + i * z
So it actually doesn't matter which major is used but it is best to be consistent with which one is used throughout a game.
All images were created using https://www.codecogs.com/latex/eqneditor.php
Matrices Pt 1
A matrix is made up of a grid of real numbers, the grid can be r rows and c columns. If a matrix has 3 rows and 2 columns it is referred to as a 3x2 matrix. A matrix is typically expressed by a capital letter. These can be used to make changes or transform a vector or position in video games. There are two ways to declare a matrix
Method 1
Method 2
Identity Matrix
The identity matrix is a matrix with equal number of rows and columns to another matrix, as well as this each component of the identity matrix is 0, except for a diagonal of 1s that start in the top left and works its way down.
Addition & Subtraction
In order to add or subtract two matrices they have to have the same dimensions or in other words, the amount of rows must match and the amount of columns must match. When adding two matrices we simply add each corresponding component together.
Matrix Equations
Matrix equations are equations where a matrix is being represented by a letter, similarly to how you might have the equation 5x = 15, which when solved gives x = 3.
An example of this is below, where we have to find A.
Scalar Multiplication
This is the same as scalar multiplication of vectors as each component of the matrix is multiplied by the scalar value.
Method 1
Method 2
Identity Matrix
The identity matrix is a matrix with equal number of rows and columns to another matrix, as well as this each component of the identity matrix is 0, except for a diagonal of 1s that start in the top left and works its way down.
Addition & Subtraction
In order to add or subtract two matrices they have to have the same dimensions or in other words, the amount of rows must match and the amount of columns must match. When adding two matrices we simply add each corresponding component together.
The same goes for subtraction as we subtract each corresponding component from one another.
Matrix Equations
Matrix equations are equations where a matrix is being represented by a letter, similarly to how you might have the equation 5x = 15, which when solved gives x = 3.
An example of this is below, where we have to find A.
The first step is to get A on its own.
Then we carry out the matrix subtraction to give us the value of A.
Scalar Multiplication
This is the same as scalar multiplication of vectors as each component of the matrix is multiplied by the scalar value.
Zero Matrices
A zero matrix is a matrix which has ever element as a value of 0. A zero matrix is represented with a 0 like below and the dimensions are subscripted to that 0.
When you add a zero matrix to any matrix you get the original matrix, whereas if you add the opposite of a matrix to the original matrix you get the zero matrix. If you multiply a matrix by zero you get a zero matrix that has the same dimensions as the original.
All images were created using https://www.codecogs.com/latex/eqneditor.php
Linear Interpolation
Linear interpolation or lerp is used to calculate a linear value that is between two values, i.e. lerp could return a value of 0.5 as it's between 0 and 1, which were the two original values given to the function. So in this instance the value is 50% between the two original values.
Lerping can be applied to a wide range of values and not just real world numbers, such as colour, vectors and quaternions. These example are made up of multiple dimensions such as colour usually being made up of 3/4 floats that represent R, G, B and A), so no matter how many dimensions make up something, lerping can still be applied using the generic formula:
Lerp(_a, _b, _f) = (1 - _f) * _a + (_f * _b)
Where _a and _b are the two points that are being interpolated between and _f is within the fractional range of [0, 1] in terms of _a and _b. It is also important to note that this formula is not frame rate independant and so by using deltaTime * _f will achieve that.
An example use of lerping is moving a platform from point A to point B, where each tick the platform's position is now a percentage between point A and point B using lerp. There are other variations on lerp such as slerp which is spherical lerping, that provide similar effects to lerping.
Lerping can be applied to a wide range of values and not just real world numbers, such as colour, vectors and quaternions. These example are made up of multiple dimensions such as colour usually being made up of 3/4 floats that represent R, G, B and A), so no matter how many dimensions make up something, lerping can still be applied using the generic formula:
Lerp(_a, _b, _f) = (1 - _f) * _a + (_f * _b)
Where _a and _b are the two points that are being interpolated between and _f is within the fractional range of [0, 1] in terms of _a and _b. It is also important to note that this formula is not frame rate independant and so by using deltaTime * _f will achieve that.
An example use of lerping is moving a platform from point A to point B, where each tick the platform's position is now a percentage between point A and point B using lerp. There are other variations on lerp such as slerp which is spherical lerping, that provide similar effects to lerping.
Friday, January 18, 2019
Unreal Engine - Blueprints Essential Concepts
What is a Blueprint?
A blueprint is a container for content as it can hold various components, scripts and data. It doesn't always need a script as it can be a data only blueprint. This means the designers can modify the data but not modify the behaviour of the blueprint.
Blueprints are a compiled object oriented visual scripting language and ties into the pre-exisiting UE4 framework class hierarchy. It is also completely embedded within UE4 and works by stringing together connections and nodes. You can also see the adjustments fairly quickly after the blueprint has been compiled.
There are two types of blueprints:
A blueprint is a container for content as it can hold various components, scripts and data. It doesn't always need a script as it can be a data only blueprint. This means the designers can modify the data but not modify the behaviour of the blueprint.
Blueprints are a compiled object oriented visual scripting language and ties into the pre-exisiting UE4 framework class hierarchy. It is also completely embedded within UE4 and works by stringing together connections and nodes. You can also see the adjustments fairly quickly after the blueprint has been compiled.
There are two types of blueprints:
- Level blueprint which is one per level and only affects that level
- Class blueprint which can have multiple instances within a level and works in all levels
Blueprints are built on C++ and in fact when using blueprints you are using C++ as they can be even openned and edited in C++. This means both play nicely together.
Creating Blueprints
When creating a new blueprint, you can pick from a parent class which gives the new class some inherited functionality (hence why its object oriented). Most cases the parent class will be an actor, however, if there is a player controlled character or vehicle the parent class would be a pawn class.
Blueprints can be created from the content browser by clicking on the add new button or they can be created by placing various components within a scene, selecting said components, then converted to a blueprints class using the blueprint button in the upper middle section of the editor window.
The default scene root component is the base object which can affect its children components. This means if that root component moves, everything else moves with it. However, if you just move the child component, then the root component will stay still. You can also override the root component with another component by dragging the new root component on top of the default root component.
You can also add components or set meshes through the content browser by dragging it from the content browser to the blueprint window.
Blueprint Graphs
Construction script fire once at runtime and whenever a change is made in the editor. It can also be used for a variety of other features such as dynamically spawning in static meshes to randomly adjust how something might look. Such as a fence and the wooden planks that make up the fence, which could be spawning in different positions and rotations to create a variety of styled fences.
The event graph is the type of blueprint graph that will most likely to be used. In here we can program how the various objects work. So if we had a security camera we can use the Event Tick function (if this was Unity and C# this would be the Update function) to make the security camera move side to side, but then when the player moves within range it tracks the players movement and the security cameras light changes to red. To check if the player is within range we could use the Event Begin Overlap (if this was Unity, it would be the OnTriggerEnter function).
In the event graph we can create function graphs which can separate functionality and organise the event graph to be neater. This can be done by selecting a group of nodes, right clicking and selecting the collapse to function option. The advantage of creating a function is that it can be reused but also used and accessed within another blueprint.
You can also do the same but create macro graphs, which are similar to the functions graphs but don't require any input values. The macro graphs are more like utility functions and are accessible only in that blueprint unless a macro library is created and used. Like the function nodes, the macro nodes can be reused if needed.
You can also collapse nodes, which doesn't create a function graph or a macro graph but just helps tidy up the event graph and keeps things organise. It is important to note that these cannot be reused.
Types of blueprints
The level blueprint is used to create level specific functionality, this might be a useful for a shooting game where the player has x amount of time to escape the level before a bomb explodes as the levels before or after that one will most likely not require that functionality. The level blueprints also don't have access to the ability to add components or access the viewport like a class blueprint can.
Actor blueprints are modular blueprints that provide various functionality and can be reused throughout the level but also multiple levels. Unlike the level blueprint you can add various components to be used by the blueprint and access the viewport to move those components around if needed.
An animation blueprint is used to create the animation logic for various characters whether they are player controlled or not. A use for this is transitioning between idle, walking, jogging and running animations for the player based on the players movement speed. Unlike the actor blueprint, the animation blueprint also has another type of graph it can use. This graph is the anim graph, which can be used to set up state machines and animation transitions. The different between the anim graph and the event graph, is that the event graph controls the moment to moment variables whereas the anim graph controls the moment to moment final pose of the animation.
UMG (Unreal Motion Graphics) UI/ Widget graphs can be used to display and control a games user interface. An example of this is displaying the players health and energy bars, as well as updating them when the player takes damage or uses up stamina. It has an event graph which can provide the functionality of the UI elements. The designer tab is used to layout and add the various UI elements.
A child class inherits from a parent class, this allows us to use functionality from the parent class but also add some customisation based on the child class. An example of this would be item pickups. The parent class would have the functionality of what to do when the player hits the trigger volume but a child class would have extra functionality on top of that, so if it was a health pickup it would give the player more health where as an ammo pickup would give the player more ammo. To create a child blueprint, you go to the parent class you wish to use in the content browser and right click on it. At the top there should be an option to create a child class blueprint.
Blueprints Caveats
Blueprint Graphs
Construction script fire once at runtime and whenever a change is made in the editor. It can also be used for a variety of other features such as dynamically spawning in static meshes to randomly adjust how something might look. Such as a fence and the wooden planks that make up the fence, which could be spawning in different positions and rotations to create a variety of styled fences.
The event graph is the type of blueprint graph that will most likely to be used. In here we can program how the various objects work. So if we had a security camera we can use the Event Tick function (if this was Unity and C# this would be the Update function) to make the security camera move side to side, but then when the player moves within range it tracks the players movement and the security cameras light changes to red. To check if the player is within range we could use the Event Begin Overlap (if this was Unity, it would be the OnTriggerEnter function).
In the event graph we can create function graphs which can separate functionality and organise the event graph to be neater. This can be done by selecting a group of nodes, right clicking and selecting the collapse to function option. The advantage of creating a function is that it can be reused but also used and accessed within another blueprint.
You can also do the same but create macro graphs, which are similar to the functions graphs but don't require any input values. The macro graphs are more like utility functions and are accessible only in that blueprint unless a macro library is created and used. Like the function nodes, the macro nodes can be reused if needed.
You can also collapse nodes, which doesn't create a function graph or a macro graph but just helps tidy up the event graph and keeps things organise. It is important to note that these cannot be reused.
Types of blueprints
The level blueprint is used to create level specific functionality, this might be a useful for a shooting game where the player has x amount of time to escape the level before a bomb explodes as the levels before or after that one will most likely not require that functionality. The level blueprints also don't have access to the ability to add components or access the viewport like a class blueprint can.
Actor blueprints are modular blueprints that provide various functionality and can be reused throughout the level but also multiple levels. Unlike the level blueprint you can add various components to be used by the blueprint and access the viewport to move those components around if needed.
An animation blueprint is used to create the animation logic for various characters whether they are player controlled or not. A use for this is transitioning between idle, walking, jogging and running animations for the player based on the players movement speed. Unlike the actor blueprint, the animation blueprint also has another type of graph it can use. This graph is the anim graph, which can be used to set up state machines and animation transitions. The different between the anim graph and the event graph, is that the event graph controls the moment to moment variables whereas the anim graph controls the moment to moment final pose of the animation.
UMG (Unreal Motion Graphics) UI/ Widget graphs can be used to display and control a games user interface. An example of this is displaying the players health and energy bars, as well as updating them when the player takes damage or uses up stamina. It has an event graph which can provide the functionality of the UI elements. The designer tab is used to layout and add the various UI elements.
A child class inherits from a parent class, this allows us to use functionality from the parent class but also add some customisation based on the child class. An example of this would be item pickups. The parent class would have the functionality of what to do when the player hits the trigger volume but a child class would have extra functionality on top of that, so if it was a health pickup it would give the player more health where as an ammo pickup would give the player more ammo. To create a child blueprint, you go to the parent class you wish to use in the content browser and right click on it. At the top there should be an option to create a child class blueprint.
Blueprints Caveats
- There is a cost associated with using blueprints over native C++ code
- It is best to avoid doing complex maths or heavy operations every frame as blueprints use a virtual machine to translate the nodes into native C++ code
- Native C++ is always going to be as it doesn't require translation via virtual machine
- There is also some functionality that can only be performed using native C++ code and therefore that makes native C++ more powerful than blueprints
- Blueprints is event based and therefore require specific events to trigger the various functionality programmed in those blueprints
- Uses refererences and therefore possible to pass an invalid reference
- It is also possible to create circular dependancies, this is where two or more blueprints depend on each other and so when one blueprint is casted to another the new blueprints dependancies are loaded, which links back to the original blueprint, whose dependancies also start to load. This then kickstarts the new blueprints dependancies again and so on.
NB. You can use casting during collision checks to see if an object is a certain type, this is similar to Unity's tag system as then you can provide specific functionality if the cast succeeds or fails.
Subscribe to:
Posts (Atom)














