The IsScrollableEntityList option on Entities allows for the quick creation of Entities which represent a scrollable list of other Entities. For example, this property could be used to create a list of high scores or a list of levels which the user can click on to select.
Benefits of IsScrollableEntityList
When using the IsScrollableEntityList you automatically have the following functionality:
- Automatic positioning of Entities in a vertical list
- Event raising whenever a new Entity is created due to scrolling
- Min and max scrolling values
- Automatic updates according to an assigned IList
The IsScrollableEntityList property takes care of a lot of the hard work when creating a scrollable Entity list.
Importing a Button Entity
The first step in creating a scrollable Entity list is to create an Entity that will be used in the List. In this case we’ll use the low-resolution brown button available here on GlueVault.com. To use this button:
- Download the .entz file
- Open Glue and create a new project or use an existing project
- Right-click on the Entities tree item
- Select “Import Entity”
- Select the .entz file and select OK. For more information on importing, see the Importing Entities tutorial here.
Creating a ButtonList Entity
To create a ButtonList Entity:
- Right-click on the Entities tree item
- Select “Add Entity”
- Enter the name “ButtonList” and press OK
- Select the newly-created ButtonList entity
- Set the “IsScrollableEntityList” to “True”
Setting the scrollable Entity list variables
Next we’ll need to tell the ButtonList that it should create instances of a Button class:
- Select the Button Entity
- Set its “CreatedByOtherEntities” to “True”
- Set its “PooledByFactory” to “False”
- Select the “ButtonList” Entity
- Change its ItemType to “Entities\Button”
- Set the “ListTopBound” to 256
- Set the “ListBottomBound” to -256
- Set the “SpacingBetweenItems to 64
Creating ButtonScreen and Layer
Now we’ll create a Screen that will store an instance of our ButtonList. We’ll also create a 2D Layer since the Button Entity and the ButtonList Entity have been designed to be used in a 2D coordinate system. To do this:
- Right-click on Screens
- Select “Add Screen”
- Enter “ButtonScreen” and click OK
- Expand ButtonScreen
- Right-click on the Objects tree item
- Select “Add Item”
- Enter “Layer2D” and click OK
- Select the Layer2D Object
- Set its “SourceType” to “FlatRedBallType”
- Set its “SourceClass” to “Layer”
- Set its “Is2D” to “True”
Adding a ButtonList Instance to the ButtonScreen
Next we’ll create an instance of ButtonList in ButtonScreen. To do this:
- Select the ButtonList Entity
- Push and drag the ButtonList Entity onto the ButtonScreen
- Glue will ask if you’d like to create a ButtonList instance. Click Yes.
- Push and drag the newly-created ButtonListInstance onto the Layer2D Object to add it to that Layer. The “LayerOn” property should automatically update
Populating the ButtonList
At this point our ButtonList is fully set up in Glue. We now need to set up the code to tell the ButtonList what it should display. To do this:
- Open your project in Visual Studio
- Navigate to ButtonScreen.cs
- Add the following code to ButtonScreen.cs’s CustomInitialize method:
List<int> intList = new List<int>();
for (int i = 0; i < 100; i++)
ButtonListInstance.ListShowing = intList;
If you run the game you should see the list of buttons. This list is scrollable by clicking+dragging with the mouse or on the touch screen.
Displaying information from items in the List
So far we’re creating Entities based off of items in a List, but there’s nothing on Screen to show that. Next, let’s modify the Text on the Button to display the integer value that the Button instance represents. To do this:
- Add the following code to ButtonScreen.cs:
// At the beginning of CustomInitialize:
ButtonListInstance.ScrollItemModified = UpdateButtonToInteger;
// At class scope add the UpdateButtonToInteger method:
void UpdateButtonToInteger(GlueTestbed.Entities.Button button)
int indexInList = ButtonListInstance.GetAbsoluteIndexForItem(button);
button.DisplayText = ButtonListInstance.ListShowing[indexInList].ToString();
Understanding the scrollable Entity list values
Scrollable Entity lists present a few properties which can control how the Entity list draws.
ListTopBound positions the first element
The ListTopBound value is a good place to begin understanding now scrollable Entity lists work because it controls the starting location of the first Entity in the list. In other words, if ListTopBound is 256 (as it is in our example) then the very first button created will be at Y = 256. Graphically this means:
Entity Position Matters We mentioned above that the position of the first Entity in the list will be at ListTopBound (which is 256 in this case). However, the position is actually ListTopBound + Y. In other words, if you expose or tunnel in to the ButtonList’s Y value, or if you modify the ButtonList’s Y value in custom code, this will impact the position of the first Entity in the list – and as a result every Entity that follows. However, for simplicity this article assumes that the ButtonList is at Y = 0.
Try modifying the ListTopBound value. You will notice that the first item will appear lower on screen if you reduce the value.
SpacingBetweenItems controls the vertical distance between items
The SpacingBetweenItems controls how Entities in the list are positioned relative to each other. In this case our SpacingBetweenItems value is 64. This means that each Entity is positioned 64 units from each Entity below and above. Increasing this value will increase how far apart they are (creating a gap between the Entities). Decreasing this value decreases how far apart the Entities are (which may cause them to overlap).
Why did we use 64? You may be wondering why the spacing is set to 64, or put another way – if you were to create a new scrollable Entity list, how would you know what to set the value to? In this particular case we were able to accurately set the scrollable Entity list value because the Entity we’re using (Button) has a ScaleY variable:
But the ScaleY is 32. Why did we use 64? The word “Scale” has a special meaning in FlatRedBall. Scale means “the distance from center to edge”. In other words, if our ScaleY value is 32, that means the distance from the center of our Entity to the edge of our Entity is 32. Therefore, the height is 2 times the ScaleY. Since 2 * 32 = 64, we used a value of 64 for SpacingBetweenItems. You can read more information about Scale in the IScalable page here
Bounds values and when Entities disappear
You may not have noticed it, but Entities will disappear when scrolling the list. To make this more obvious, you may want to change the ListTopBound and ListBottomBound values to 128 (and -128) instead of 256. This will lower the top bound and raise the bottom bound so that fewer items are visible on screen
If you reduce the bounds and then try scrolling the list, you will notice that as you scroll it up, new Entities are created at the bottom of the list (with increasing values) and existing Entities are removed off of the top of the List. This is desirable for a number of reasons:
- It keeps the number of live Entities small to improve performance and keep memory usage low
- It allows you to place Entities within a container instead of having the list always extend to the top and bottom of the Screen
The ListTopBound and ListBottomBound values control how high (or low) an Entity must be before it disappears. In strictly numerical terms, an Entity will disappear from the the top when its Y value is greater than (ListTopBound + SpacingBetweenItems). An Entity will disappear from the bottom when its Y value is less than (ListBottomBound – SpacingBetweenItems). In our specific case our values are:
- ListTopBound = 128
- ListBottomBound = -128
- SpacingBetweenItems = 64
This means that an Entity will disappear from the top when its Y is greater than 128 + 64 = 196. An Entity will disappear from the bottom when its Y is less than -128 – 64 = -196. Grapically this looks like this:
Why is Button “5” not removed? You may be looking at the list and wondering why button #5 is present. The reason for this is because the scrollable Entity list has no idea how large the Button is – the logic for creating and removing Entities does not work based off of size. Instead, it works based off of position. Therefore, an Entity is removed if its center is within the striped pink area.
Of course, you may be wondering why Button “5” isn’t removed – it appears as if its position falls within the area. The reason is because its position is right on the border. Due to floating point inaccuracy, it’s difficult to predict whether an Entity will be included or excluded when it falls right on the border. The important thing, however, is that you understand that once it moves into the area, it will be removed.
Applying a Mask
Although the scrollable Entity list functionality is very useful, the removal and addition of Entities may be a little jarring. Your game may instead want to use this with a display region – in other words, to have Entities disappear pixel by pixel as they move beyond a set area. The scrollable Entity list does not have functionality for this built in; however, scrollable Entity lists can be used in combination with Layers in Glue. Furthermore, the DestinationRectangle property on Layers can be set in Glue to implement masking without any code.