Go to content

Creating Level Selection Screens in Multimedia Fusion 2 and Clickteam Fusion

Last Updated: January 17th, 2016
Throughout your various games, you may lock some levels and force the player to unlock these levels via gameplay. Due to lack of a better term, I'll call this a "level selection" mechanic. Basically, some subset of levels are initially locked. While a handful of levels are initially accessible to the player. As the player progresses through the game, various levels are unlocked. This tutorial will introduce the required fundamentals to execute this mechanic and explain how to easily implement these fundamentals.

Concept
Introduction
This mechanic is built solely by the comparison of two bitmasks. There is one set of objects (Levels) which represent the currently accessible levels the player may select. Each of the level objects have two variables; Level_Requirements and Level ID.

The Variables
One global bitmask (Completed_Levels) represents which levels are fully completed while the other object oriented bitmask (Level_Requirements) specifies the prerequisites for a given level. If the expression "Completed_Levels AND Level_Requirements = Level_Requirments" is true, then the object with the Level_Requirements is accessible.  A Level's Level_ID is an integer ranging from 0 - 31. When a level is completed, the nth bit (Level_ID) of the Completed_Levels bitmask flips on.

Saving Completed Levels
After a level is completed, we need to update Completed_Levels to reflect the current state of completed levels. This modification is performed by modifying Completed_Levels with the following expression: "Completed_Levels = Completed_Levels OR Level_ID".

For those familiar with basic graph theory, the way some items must be played/accessed before other items resembles a directed acyclic graph. As such you can apply some graph algorithms, such as topological sorting, on the item set.
Introduction Material: The Itty Bitty Bits of Numbers
With respect to electronics, numbers are composed entirely of 0s (off/low/false) and 1s (on/high/true) called bits. As such, numbers are expressed in binary. MMFusion, integers are represented with 32 bits with the 0th bit as the least significant bit and the 31st bit as the most significant bit

**Note**
Usually, bits are divided into groups of four for visual clarity.

Examples Decimal Integers Expressed as 32-bit Binary Numbers:
1 = 0000 0000 0000 0000 0000 0000 0000 0001 = 1 (simplified form)
2 = 0000 0000 0000 0000 0000 0000 0000 0010 = 10 (simplified form)
100 = 0000 0000 0000 0000 0000 0000 0110 0100 = 11 0100 (simplified form)
777 = 0000 0000 0000 0000 0000 0011 0000 1001 = 11 0000 1001 (simplified form)
-1 = 1111 1111 1111 1111 1111 1111 1111 1111 (simplified form)

This mechanic simply requires knowledge that MMFusion expresses integers with 32 bits, though additional useful topics which you can research are listed below.

• Two's Compliment (Expressing Negative Numbers in Binary)
• Converting Decimal Numbers to Binary
Introduction Material: Bitwise Operators
As there are numeric operators (add, subtract, multiply, etc..) for numbers, there are also bitwise operators for bits. The examples in the above tabs operate on a bit-by-bit basis. The rightmost bit of the first number is compared with the rightmost bit of the second number, the second rightmost of the first number with the second rightmost of the second number, etc...

More information about bitwise operators and Expression Editor functions may be viewed at the Expression Editor Basics tutorial.
In short, bitmasks are a data type similar to strings and integers. Bitmasks are typically composed of a certain number of bits, such as 32 or 64. As such, numerical data types, such as integers, can act as a bitmask. Actions, conditions, and expressions involving bitmasks compare or act on individual bits, rather than the numerical value itself. In MMFusion, Object Flags constitute a basic bitmask, though manipulating multiple flags is lengthy and gruesome. As such, this tutorial uses Global Values and Alterable Values as bitmasks.
The Importance of the AND and OR Operators
As mentioned above, the AND operator returns a 1 only when the two input bits are 1. How is this operator useful for the level selection mechanic? Suppose there are eight levels. Three of which; A, B, and C have specific prerequisites. A has no prerequisites, B requires completion of A, and C requires completion of B which, in turn, requires completion of A. Example Level_IDs and Prerequisites for the levels appear below in the format "Variable_Name: [bitmask binary number] (decimal number)"

Level A:
Prerequisites: [0000 0000] (0) (no prerequisites)
Level_ID:  [0000 0001] (1) (used if any level needs A as a prerequisite)

Level B:
Prerequisites: [0000 0001] (1) (A as a prerequisite)
Level_ID: [0000 0010] (2(used if any level needs B as a prerequisite)

Level C:
Prerequisites: [0000 0011] (3) (A and B as a prerequisite)
Level_ID: [0000 0100] (4(used if any level needs C as a prerequisite)

Also suppose that, initially, the number of Completed_Levels variable is the following: Completed_Levels: [0000 0000] (meaning no levels are initially completed)

Accessible levels can be determined by ANDing the Compled_Levels and Prerequisites. If the result of the operation equals a level's Prerequisite value, then that level is currently accessible. Given the above values, only Level A is accessible.

Level A              Level B               Level C
0000 0000            0000 0000             0000 0000 (Completed_Levels)
0000 0000            0000 0001             0000 0011 (Prerequisites)
=========            =========             ========= (AND Operation)
0000 0000            0000 0000             0000 0000 (if the level is accessible, this should match the level's Level_ID)

If Completed_Levels was [1100 1011] (203), all three levels would be accessible as shown below.

Level A              Level B               Level C
1100 1011            1100 1011             1100 1011 (Completed_Levels)
0000 0000            0000 0001             0000 0011 (Level_ID)
=========            =========             ========= (AND Operation)
0000 0000            0000 0001             0000 0011 (if the level is accessible, this should match the level's Level_ID)
By now, we know electronics express numbers in binary form through the use of 1s and 0s, also called bits. A continuous set of bits constitute a bitmask, which in can be expressed through numerical data types such as integers. The bits that compose a bitmask have specific operations associated with them; the AND operation turns bits off (to 0), the OR operation turns bits on (to 1), and the NOT operation inverses all bits in a bitmask. How does this information allow us to create a level selection mechanic?

As mentioned in the Concept, three bitmasks are maintained; global variable Completed_Levels, object variable Level_Requirements, and object variable Level_ID.
• Completed_Levels represents the state of up to 32 unique levels. Each bit represents the completion status of one level. A level is considered unfinished if its corresponding bit is 0 and finished if its corresponding bit is 1. As levels are completed, the nth bit (based off of Level_ID) of Completed_Levels is turned on through the OR operator.
• Level_ID represents the level's corresponding bit (0 - 31) in Completed_Levels variable. When levels are completed, their Level_ID is ORed with the Completed Levels, effectively unlocking more levels.
• Level_Requirements represents the absolute minimal requirements before a specific level is accessible. A given level is considered accessible if the evaluates true: Completed_Levels AND Level_Requirements = Level_Requirements.

Summary
There is nothing more to this mechanic outside of the bitmasks and bitmask operators. There are three aspects which might generate issues.
1. Improperly or incorrectly setting up the required values
2. Improper use of the AND/OR operators
3. Incorrect object scoping to an individual level.

Limitations:
MMFusion builds a 32-bit application so all numerical values are limited to 32 bits. As such, you will only be able to express 32 levels per bitmask. You will need to use and maintain multiple sets of Completed_Level, Level_ID, and Level_Requirement variables or use Alterable Strings if you wanted more than 32 levels.

Alternative Methods:
You can also use topological sorting if you can arrange the set of data into a directed acyclic graph. All nodes which have no inbound nodes are possible options for the user to select.

Rate This Tutorial
Vote: 2.5/5
If you have read this tutorial, rate it from poor (1) to average (3) to great (5)! 