ASTRA Aquarium Documentation
The Aquarium uses all ASTRA 1.0 Components, i.e. Tree, Menu, TabBar, AutoComplete, and Charts in a fun application. As such it shows how to integrate these components in a real application and how to customize these components for special use.
- Custom skins for Buttons, TabBar, and Tree
- Tree with custom CellRenderer featuring additional interaction and animation
- AutoComplete integration with Tree by expanding the Tree via actionscript
- Using Charts to display statistics
The application has three main modes:
The different modes of the application are layed out on the time line.
Each component is added at the appropriate point on a layer. Actions for setting up the components (e.g. dataProviders, eventListeners) are kept on one layer. For example, the Menu component is added on it's own layer at frame "start", AutoComplete is added on its own layer starting at frame label "add Fish" etc. Except for the Menu, all components are dragged on stage and initialized through ActionScript in the main Flash file. We will comment on each component below. Please refer to the actions layer for taking a closer look at how we initialize each component.
Apart from the initialization of the components we created a class hierarchy and separate class files for our aquarium to keep things organized. The class files used in this example are:
- FishTank: This is our document class and can be seen as the main controller of the application
- KineticObject: An abstract base class for moveable objects based on a physics model
- Fish: Our main object we are adding and animating in our aquarium. It extends KineticObject
- PhysicsModel: This class handles the 2D physics calculations used by our fish
- FishCellRenderer: Our custom cellRenderer for the Tree to display our fish in the tree cells.
- FishEvent: A custom event to propagate the addFish-event from our cellRenderer to the Tree.
The menu is inserted in a very simple way and used to switch between daylight and nighttime modes of the aquarium..
This is a very much standard use here: We are using ActionScript to create Menu as well as set it's position and with/height. A simple XML as dataprovider is used and an event listener defined that tints the frontGlass object of the aquarium to achieve the desired effect. Note that we also specify the icons for the menu entries as part of the XML. A Button is used to show the menu (see layer actions at frame label "start").
The TabBar is also used in a simple way. We initialize it with the label fields as well as the frame label to jump to when a tab is clicked. Note, that the same changeHandler function can be used when switching TabBars between "add Fish" and "settings" modes in our application. We also modified the skin - by copying the assets and assigning the new skins - to give the tabs some transparency and a different shape.
For Tree we define a simple XML dataprovider that lists all of our Fish. We also set a custom CellRenderer and define an eventListener for our custom Event "addFish" which the FishCellRenderer will create. The handler will then call the addFish Function from the document class (FishTank). Note that the cellRenderer does not have access to that class so creating this custom event allows this message to be passed. The Tree also has a customized skin, again by copying the assets and assigning the modied skins to the tree instance, i.e. adding rounded corners for background and cells, modify cell colors, modify the plus and minus icons.
We didn't want to create a separate dataprovider for AutoComplete in case we would modify our fish hierarchy or would add anything to it. Hence, we wrote a conversion function "parseTreeToLabelArry()" that creates the an array of the leaf-node labels and is used to initialize a new dataprovider for AutoComplete.
There are three ways to expand the Tree to display the fish from AutoComplete: 1) Clicking on a proposed Fish from the Autocomplete Menu, 2) pressing Enter on in the Autocomplete field or menu, or 3) clicking on the "Fish Search" button. For each we need to do slightly different things. When clicking the button we also need to make sure we are displaying the Tree tab since we could be displaying the charts statistics when the button is clicked. Hence, we set the selectedIndex to "0". Once a fish is selected we would like to display the Tree in the appropriate expanded state. The Tree supplies a function exposeNode() and closeAllNodes() that makes this a simple task.
Charts in this example is very straight forward and mainly displays the current tally of fish in the tank. Note that it gets updated when you add a few fish and click back on the "Statistics" tab to display the chart again. The only small customization we did was creating a new toolTip and a label function in order to display the toolTip on one line and the fish name in the label function (instead of the default percentage). We added a setStyle call in order to display the labels in the chart. In the future we like to add more visuals to charts and maybe showing the fish itself in the toolTip.
Now that we described the main structure of the application and commented on how each of the ASTRA components has been integrated, let's now look at some more details of the FishCellRenderer and the PhysicsModel that we implemented:
This is probably the most complicated element of the entire application. We needed a custom CellRenderer in order to display the fish icons in the Tree. This gets achieved by choosing the right icon when the listData gets set. Here, for each fish name in the TreeDataprovider we have defined a corresponding symbol icon that we can retrieve through the getDefinitionByName() function.
We also need to size and position the icon in the drawLayout() function. Here we also position the "add" button that allows the user to actually add the fish. Note that we use the function setIconSize() to apply a heuristic for rescaling the fish sizes by keeping into account the limits of the cells. This way we still have differences in fish size but they all fit into the Tree cell.
The last thing to do is adding the animation of the fish when the user clicks the add button. Here, we initiate a Tween and trigger our custom FishEvent "addFish" whenever the add button is pressed. This event gets then handled by the Tree.
However, due to the fact that the drawLayout() function is getting called immediately after a mouseUP event or when the user rolls-out of a cell, we do have to integrate the Tween into the drawLayout() function itself. So, when we "animate" we create a new Tween when none is current, hide fish, label, and add-button, and register a listener for the end of the Tween. Once the Tween finishes we re-display the fish icon, the label, and the add-button.
For this example we implemented a simple force/acceleration model to animate the fish. We take into account that water has a drag coefficient and we create a repellent force with the wall coefficient. Each axis is handled separately for simplicity. Below we show the main function that calculates the forces at each frame:
A lot of additional things could be added here but we thought we leave this example very simple to highlight more the use of the components than sophisticated game physics. Adding some more animation to the fish (e.g. pedaling motion) and some more behaviors (less constant swimming speed) as well as interactivity on mouse-over would be fun to add at some time in the future.
application concept + implementation: michael hoch
tree component: allen rabinovich
menu + autocomplete components: alaric cole
charts + tabbar component: josh tynjala
interaction design: lucas pettinati
graphic design: stephan douris