Technical Guide for Director Projects

ëTechnical Guidelines for Director Projectsí was written by Andy Wilson and is ©1996 Red Kite New Media.
Unauthorised reproduction and copying prohibited.

Section One : Aim of the Technical Guide

Section Two : Organising the Project

Section Three : Project Conventions

Section Four : Preparing Media Assets

Section Five : Assembling the Project

Section Six : Optimising Performance

Section Seven : Conclusions


Section One : Aim of the Technical Guide

Why we use a Technical Guide

Whether it takes the form of a screensaver, kiosk, web site or straightforward presentation, a multimedia project involves the organisation of various media types - bitmaps, digital video, text, audio, MIDI - into a single interactive environment. This often means preparing and optimising hundreds of megabytes of different media types to integrate them into the project. In the majority of cases we are using Macromedia Director as our authoring environment.
The fact that a project can be delivered by many different means (such as floppy disk, CD ROM, an intranet or internet, and so on) and to many different delivery platforms and operating systems, means the technical problems in designing and implementing a project can become very complex. Add to this the fact that the technology itself - the software, protocols, specifications, hardware, bandwidth, standards, techniques - changes from day to day, and you begin to sense the scale of the technical issues involved in managing a project successfully.
We must also take into account the fact that members of the production team often have very specialised skills, without an in depth knowledge of other aspects of the total production process yet their work impacts the whole project. Therefore we need to establish a general awareness of these issues across all members of the production team and create working practices to maximise the effectiveness of our work.
The aim of the technical guide is ;

  • To make all members of the team aware of the general technical issues involved in preparing a multimedia project using Director as the authoring environment. This should help everyone to better understand the context in which they are working when they are involved in any particular project.
  • To establish guidelines governing how we organise and control assets within Macromedia Director. Basically this means establishing good general methods when working with multimedia in general and Director in particular.
  • To lay down certain conventions which should be adhered to by all members of the production team at all times.
  • Aims of Good Project Design and Implementation

    Inasmuch as we are talking about technical design, the aims of good design are ; economy, concision, consistency, speed, clarity, scalability, reusability.

  • Economy : we should minimise the effort required to create the assets, avoiding unnecessary repetition (economy of effort). We should minimise the use of resources (disk space and memory, for example) to the extent that is compatible with good interface design (economy of resources).
  • Concision : the conceptual equivalent of economy, the aim is to optimise the structural relations between assets, creating clear relations which allow the project to be easily modified, maintained and understood.
  • Consistency : similar methods, techniques, palettes, layouts, fonts, colour depths, etc., should be used throughout a project where compatible with the design goals and client needs as a whole. A consistent approach to technical issues makes maintenance easier and enhances the design integrity (ëlook and feelí) of the product.
  • Speed : much multimedia work is undermined by a failure to take into account that end users often have lower specification machine than those used by developers. Because the project has not been properly optimised, performance on the usersí machine is poor. With a properly managed project there is no reason why it should not be optimised for the best possible performance on the lowest spec machine we can reasonably expect to be authoring for.
  • Clarity : our programming conventions, the way we organise assets, how we archive resources, etc., should all make it as clear as possible what the purpose of a particular file, handler or line of code is within the project as a whole. This makes it easier to maintain and develop a project.
  • Scalability : all aspects of project development should take place with an eye on the possibility of the future expansion of the project to include new assets, updated data, extra modules, etc. If scalability is built into our programming and data management assumptions it is easier to expand the project in the future.
  • Reusability : Where it is compatible with the nature of a particular project, all code written and all assets created should be designed to take into account the possibility that they may be reused in future projects. Why reinvent the wheel or, indeed, the database engine? Obviously, this is an important issue for programmers.
  • Status of the Technical Guide

    All members of the production team should read this guide, make themselves aware of the general issues raised, and attempt to follow the methods described. All members of the team will be required to follow the specific rules and conventions detailed here.

    A Note on CD Performance

    The advent of CD technology massively increased the amount of data that could be delivered economically to end users, allowing developers to include audio, animation and video files as an integral part of work targeted at a general audience.
    However, as Obi Wan Kenobi said, there is a dark side to the force. Because as well as allowing developers to deliver huge amounts of data to the userís machine, the low bandwidth and slow access time of the CD also limits the rate at which this data can be delivered from that machine to the actual user.
    Even with the advent of new four- and eight-speed CD players, the rate at which data can be read from most userís CDís is still slow enough for it to form the major bottleneck in most of our work (only the internet is slower, which means that the problem is even greater when authoring for Shockwave).
    Many users have a two-speed CD drive, which limits the data access rate to something in the region of 300 Kbs (300 kilobytes per second). A multimedia application which tried to load a 16 bit 640 * 480 image as a background while also trying to start a 16 bit, 22 kHz stereo audio file would run into problems immediately. The audio file would need to be reading in about 88 Kb per second just to keep playing while Director also tried to load up an image around 100 Kb in size, and all the time the CD read head would be skipping back between trying to stream the audio off the disk and trying to read in the bitmap in order to draw the next frame, slowing things down yet further. The likely outcome is that the audio would ëstutterí while the program dragged itís feet trying to load the image.
    In this example we havenít even started talking about playing a QuickTime or MPEG file, which have much higher data rates, and we simply assume that the user isnít running other programs at the same time, which would degrade performance even further. This is why many multimedia productions delivered on CD perform like a man trying to suck a marble through a straw.
    For an application to stand a chance of playing even reasonably well on such a (not at all unusual) machine, we would have to make every effort to see that all the resources used by our program, and the manner of its presentation, had been optimised so they used as little of the machinesí time as possible. Only then could we hope to get the user to take our CD seriously as a piece of interactive multimedia, as opposed to an electronic beer mat.
    That is why we have a style guide : to make sure that at every stage of a project, from design and specification, through assembling the assets to pressing the gold disk, we understand how our decisions and working practices will affect the performance of our product on a userís machine.


    Section Two : Organising the Project

    Choice of Delivery Platform

    Whether we deliver a project for Mac or PC or both is not in itself a technical question. Wherever possible we should create a cross platform version of the project.
    Exceptions to the rule occur when we know that the end users have a particular machine. This happens when we create work for kiosks, in which case we can specify the kiosk machine and so determine what the delivery hardware and operating system will be.
    Another exception occurs when we need to use a specialised technology which can only be delivered on one platform or where porting it would take a disproportionate amount of effort. For example, we may decide to use an Xtra or Xobject (Director extension) which is only available for Windows. In that case, if Mac users do not make up too significant a proportion of the target audience we will deliver the project as a Windows-only application.

    16 bit Windows vs. 32 bit Windows

    With Director 5 we are able to target both 16 and 32 bit versions of Windows. In fact it is very simple for us to target both platforms at the same time. We can do this by preparing the bulk of the project as linked Director movies (where each section of the project is a standalone director movie and can therefore be played on either platform without modification - and, indeed, could even be used by the Mac projector if we deliver a hybrid CD ROM). A stub director movie is then created which calls the first section of the main project. This stub can then be compiled twice - once for Windows 3.x and once for Windows 95 and Windows NT. Director 5 ships with a ëlauncherí utility which automatically detects which version of the operating system is running on the users' machine and automatically launches the appropriate stub. All subsequent movies in the chain are identical for both 16 and 32 bit Windows users.
    In this way we can create software which can run on either version of the Windows operating system. Since this method is easy to implement, uses up very little extra disk space (relative to the size of a CD ROM) and is just as easy for the end user to use (they start the same ëlauncherí application in both cases) there should rarely be any excuse not to give the client the advantage of catering to both flavours of Windows.
    We should always use this method unless space dictates otherwise, in which case we should develop for the 16 bit platform.

    Cross-Platform Issues

    Use of Palettes

    When developing a cross platform project in 8 bit depth, the graphics should be prepared using the Windows 8 bit palette (where we are not using custom palettes, of course). Switching between the Windows and Mac system palettes when changing movies causes flashing on many systems. When developing for Shockwave we should always use the 8 bit palette optimised for Netscape. Both of these choices represent de facto industry standards.

    Control of Monitor Colour Depth

    On the Mac it is possible to reset the color depth of the usersí monitor whereas on Windows it is only possible to detect the existing colour depth and issue a warning if it is not appropriate.
    This is a significant issue since most graphics will perform relatively slowly if they are being displayed on a monitor with a different colour depth. It is recommended that in the Mac version of a project we reset the monitor depth as appropriate while on the windows side we issue an alert informing the user that the application looks and performs better in the appropriate colour depth.

    Audio Issues

    Due to itís origins on the Mac platform, Director seems happiest using AIFF files rather than the Windows-based WAVE format. It is recommended that we use AIFF format files in both Windows and Mac projects.
    Another complication with delivering sound under Windows concerns the audio channels. Since the audio capabilities of Wintel machines were never standardised, some older machines can only play one channel of audio. Therefore, although Director has two sound channels in the score, when targeting Windows machines it is worth bearing this limitation in mind. Nevertheless, there will be many cases in which the advantages of being able to use two channels outweighs this consideration, especially since more and more Windows users have newer sound cards capable of playing both channels.
    Note also that Windows cannot play either of its sound channels while QuickTime is playing - the system will not mix regular and digital video sound.

    Flattening QuickTime

    QuickTime movies should always be flattened. That is, they should be saved in Movie Player as ëSelf-Containedí and ëPlayable on non-Apple Computersí. Only flattened movies will play under Windows (technically, the process involves collapsing the fileís resource fork into itís data fork, making it compatible with the Windows file system) and, while there is a theoretical degradation of performance on the Mac, in practice this is insignificant.
    Because QuickTime is not part of a standard Windows installation and even on Macintoshes the user may have removed QuickTime from their system to save memory, we should always test for the presence of QuickTime (using lingoís 'the QuickTimePresent' command) when an application that uses QuickTime is launched and tell the user to install it if isnít already present.

    Coding Across Platforms

    Lingo, the coding language used by Director, is almost completely cross platform compatible. Nevertheless there are some platform specific effects which a cross platform project will have to address.
    For example, file paths are described differently across the two platforms. To play a movie under Windows in the relative path ìmyProj\movs\myMovî I might issue the command

    while on the Mac I would say 

    In this and similar cases the solution is for the stub movie of the project to detect the platform and set up a global variable called, letís say gPathSep, appropriately. For example

    Whenever a file has to be called you can use this global to make the code
    
    cross platform compatible



    In all cross platform projects there should be a handler in the calling projector which initialises the values of all platform dependent variables, initialises the appropriate Xobjects and carries out any platform specific tasks. In the case above, the only alternative would be to either redetect the machineType value every time a path had to be called - inefficient and slow - or create two versions of the project and hard code in the path values for each platform.This abandons the power of Director as a cross-platform authoring environment and commits the rest of the development team to having to do twice the work to maintain two otherwise identical files.

    Choice of Colour Depth

    The temptation in many cases is to assume that the greater colour depth used in a project, the better the project will be, with all graphics in ëmillions of coloursí (32 bit colour - that is, 32 bits of colour information for every pixel in the picture) as the best possible option. In fact, in most cases using a lower colour depth will have little impact on the look of the project and will give a significant boost to the speed and responsiveness of the application.
    Because of the amount of data that has to be transfered for 32 bit graphics (twice as much as for 16 bit, four times as much as 8 bit, and so on) this colour depth is always going to perform slowly. The same is true to a lesser extent of 'thousands of coloursí (16 bit colour) but with the added complication that, for technical reasons, this format adds an extra processing overhead when drawing screens (although it is still faster than 32 bit colour). Another consideration is that neither 16 bit nor 32 bit colour images allow their palettes to be controlled from within Director.
    In many cases, 256 colours (8 bit colour) is perfectly adequate from a design point of view. Certainly it is far easier to control and manipulate from within Director, performs much faster during screen redraws, and a file saved in this colour depth will be much smaller than the same image stored at a higher colour depth.
    Using palette cycling and palette transitions it is possible to achieve some very sophisticated effects in 8 bit colour depth. Also, we can prepare dedicated 256 colour palettes to match our images, giving us very good colour quality even with 8 bits. Put all this together and it becomes clear that we should have a strong bias towards using 8 bit colour, especially when the application is aimed at a general audience and we do not control the specification of the target machine.
    For Shockwave we should always use a dedicated 8 bit Netscape palette since performance is unstable at any greater bit depth, and for the moment we can assume that Netscape is the de facto standard for web browsers.

    Designing Interface Components

    In designing an applicationís interface and program flow, after all artistic and interactive design decisions have been made but before actual preparation of the screens begins, we need to make a further analysis of how best to break up the elements of the inteface into logical components.
    Pressure of deadlines, etc., has sometimes meant that in the past we have designed the screens for a project and then simply imported each of them into Director, so in moving from one screen to another we are unloading the whole of the old screen and then loading up an entirely new screen to replace it. This is hugely wasteful of system resources and is unacceptable practice.
    Instead we should break down each screen into its component parts - background, buttons, icons, logos, etc. - and import these elements rather than importing whole screens. Alternatively we can import a whole screen, copy it and then delete all but the relevant element - useful since it means the element then has the correct registration point relative to the screen.
    In the example above this would mean that between the two screens we might use the same background, buttons and icons but simply change some text or a picture. This would mean that the size of the whole project would be reduced since we do not have to store multiple copies of the same background in the cast. Also the program would change screens much more quickly since, for example, it wouldnít have to load a whole new background but use instead the background already loaded.
    This must become standard practice on every project we do.

    Building in Time to Optimise

    In our project planning we should set aside time at the end of a project, after all assets have been assembled and incorporated into working movies, to optimise the applicationís performance, overcoming bottlenecks by unloading and preloading cast members as appropriate.

    Building in Time to Debug

    We should also set aside time, after optimisation is complete, to thoroughly test and debug the project. Since new code is being added to projects right up to the last moment of the production phase, we cannot just hope that an application will behave as specified or even that it will not crash if we have not had time to test it and fix the bugs that will, inevitably, emerge. We should build in a distinct ëOptimisation and Debuggingí phase at the end of the project schedule during which no more modifications or additions to the program can be made.

    God is in the Details : Finishing the Project


    Section Three : Project Conventions

    Filenaming Conventions

    If the project is targeted at Windows or is to be delivered on an ISO 9660 format CD, all files in the project itself (as opposed to preparatory work), including all linked files, QuickTime movies, external sound files, etc., should follow the 8.3 naming convention. That is, files should be named using only alphanumeric characters without spaces (ie. you canít use ¬`ë!î£$%^&*()_+-={}[];:@í~#<>,./? TAB or SPACE) should have a maximum eight characters in the first part of the name and should have a three letter extension. Similarly, all directories in the project should be named with a maximum of 8 alphanumeric characters.
    Note : our network currently truncates longer filenames to 8.3 format when transfering them between Macís and PCís. When it does this it adds an exclamation to the front of the name. Since Director will happily link to such a renamed file on either platform it is easy to forget that you will need to rename the file again if it is to be put on an ISO 9660 CD. We can end up having to rename the file and then open, relink and save every movie that uses it five minutes before going to pressing. In the worst case the file will be renamed automatically by the CD authoring software. Then the movies that use it will fail to find it when run on the userís machine, causing error messages.

    List of Standard Extensions

    When naming files, use the conventional extensions for that fileís format. Extensions for files commonly included in our work are :

    Directory Structures During Development

    Directory Structures During DevelopmentWith several people working on the same project at the same time we often end up with development files scattered across different machines on the network in folders which are difficult to identify. Similarly, files we need often turn out to have been deleted or we end up with large amounts of useless data sitting on drives because no one knows whether they are still needed for a project.
    We should use a directory structure during development which makes it easy to identify all files connected with the project and we should build it in one central location, namely the main server on the multimedia group network. The basic directory structure should be built right at the outset of the project before we even begin collecting and building assets and resources. The correct method of working would be to move (as opposed to copy) a file onto a local hard drive then move it back up to the server when finished. This way we avoid the possibility that two people will be working on different versions of a file.
    Although the exact directory structure of any project will be peculiar to it, the figure below shows what should be a typical structure for a large project.

    Directory Structures in the Project

    Graphics

    At the moment graphics tend to be prepared in Photoshop in thousands or millions of colours then dithered down to the appropriate colour depth when they are imported into Director. This is not an efficient way of preparing graphics. Instead, graphics should be prepared in millions of colours and then either dithered down to a prepared or custom palette in Photoshop or dithered using Debabeliser when we want to create graphics with a shared custom palette.

    Audio

    Audio files can be very resource intensive, taking up disk space and hogging memory. As discussed earlier, it is important that we use audio with the lowest sampling rate and resolution compatible with the delivery medium and the nature of the audio.
    To give an example, the size of any sound file can be calculated by the formula

    So ten seconds of 44 Khz 16 bit stereo audio should be about 1760 Kb, while the same audio sampled in mono at 22 Khz with a resolution of 8 bits would be only 220 Kb, and so would take up an eighth of the disk space, load in an eighth of the time (or less) and would be processed eight times more quickly.
    It is difficult to imagine any circumstances in which we would use 44kHz sampled audio. We should use 8 or 16 bit audio sampled at 22kHz or, where sound quality is not crucial, 11kHz.
    In certain circumstances it may be worth preparing audio as IMA 4 compressed, audio-only QuickTime, as this gives both very high quality and very efficient compression. One project I worked on used 2000 audio files and was to be delivered on four CDís in a caddy. Using IMA 4 QuickTime files we were able to put the whole project onto a single CD without a noticeable drop in quality.

    Digital Video

    QuickTime video is extremely resource hungry and we should do everything possible to drop down the data rate of QT files as far as possible. For QuickTime on a CD we should prepare the movie at a maximum of 15 f.p.s, and a maximum data rate of 200 Kbs (though it is better to aim for around 150 Kb), with keyframes every 5 frames. For a CD based project the maximum window size for the movie should be 320 * 240.
    Which compression codec we use depends on the nature of the material to be compressed, whether the user will be playing the video from a hard drive or CD-ROM, and the processing power of the userís machine. Basically, the Animation Codec gives the best quality video, but produces very large files. We should use Animation compression when we are preparing video for a kiosk, since the video will be played from the hard drive and we can therefore handle the high data rates that Animation compression requires. For CD-ROM based work we will almost always use Cinepak compression which produces fairly good quality results in a file about half the size of an Animation compressed file.

    QuickTime VR

    Most of the above applies also to QTVR with the addition that object movies can have a window size of up to 400 * 300, and panoramic movies of up to 450 * 320, though we should usually aim for something between 320 * 240 and 400 * 300.


    Section Five : Assembling the Project

    Introduction to Director

    Director is the premier authoring tool for the kind of multimedia work we are engaged in. Approximately half of all multimedia CDís in the world today were built using it. Director is cross platform, supports an extremely wide range of formats and data types, is based on a metaphor which is intuitively easy to understand, embodies a scripting language which gives the user incredible control of the environment and has a programming interface which allows it to be extended almost indefinitely. Also, even though the metaphor it is based on (of stage and casts) is essentially linear, Director not only allows you to build totally object orientated projects but is itself fundamentally object orientated. All this makes it an extremely powerful production tool.
    From a production point of view, however, Director has one major flaw - it is far too forgiving of bad design and bad programming. Almost anybody can throw huge amounts of bloated data into Director, not bother to organise it properly and still the compiled application will run. Of course, it will run like a dog with itís back legs tied together, but hey, ìit worksî.
    While this situation is excellent from one point of view - it means that learners can build their first multimedia project very quickly using Director, without any deep knowledge of either multimedia in general or Director itself - for a professional multimedia team it is a real problem. Comparing Director to many other authoring tools is like comparing a hawk to a chicken - a hawk can soar much higher than any chicken can fly. Unfortunately, a hawk can also flap along quite happily with the rest of the chickens. Ultimately, Director is only as good as the people who use it and we must learn to overcome the generosity of the Director environment to make sure our work flies more often than it flaps.

    Design of a Director Project - Scalability and Encapsulation

    We have already discussed the need to build scalability into the project design. What we are discussing now is the way we apply the same principles when implementing the project. In the first place it means building it in such a way that it is possible to plug in new modules fairly painlessly. The key to this is to organise the functionality of a project so that itís elements remain logically and operationally discrete, so that it can then be called not only from existing parts of the work but from new sections that may be added later.
    Imagine we have a project whose opening screen consists of a menu which then points to two large, distinct subsections. The obvious way to implement would be to make the movie holding the main menu initialise the whole project, launch any child objects as necessary. Then each subsection should be made self-contained so that the main menu can call either of them with a single line of lingo, eg.


    where ëinitSectioní is a handler which performs the appropriate initialisation to launch one of the projectís subsections. Doing this, it would be possible to add further sections in the furture which are self-contained and simply 'plug iní to the existing project.
    The same logic should be followed at every level of the project - so each section of the project is divided into subsections. Of course, the real art here lies not in announcing to the world that we should do this but in deciding in the context of a particular project which parts need to be separated out as self-contained elements and which do not. It would be easy to make every bit of a project a stand-alone unit even where it was not strictly necessary but that would create extra work to no purpose and make the structure of the project too confusing.
    The key to making these decisions lies in the idea of ëencapsulationí. This requires that each project module encapsulates a piece of the programís functionality which can then be shared between different parts of the program. The limit to the endless proliferation of project elements is that, wherever possible, a discrete part of the programís functionality be embodied in a single object (which may mean a single Child object, a single handler, a single movie, or a single resource). Encapsulation will be discussed further below.

    Organisation of a Director Project

    linked vs. imported graphics

    In the past we have assumed that externally linked assets make it easier to build a project. For example, in the case of graphics we have built projects which contain hundreds of externally linked PICT files. The argument for this is that it enables the files to be more easily edited. The external file can be opened up in Photoshop and edited from there, and the edits will be reflected within the Director movie without us ever having to open Director itself.
    In practice, however, we very rarely rely on this ability. Instead, graphics are prepared in Photoshop and then brought over into Director. Any subsequent modifications tend to consist in trimming the file and adjusting its registration points, etc., all of which can be done more easily in Directorís paint window, in which case we may as well bring the graphics into a Director cast library rather than linking to them.
    There are other reasons for preferring to import graphics rather than link to them.

    For these reasons we should use imported rather than linked graphics.

    multiple movies, multiple cast libraries

    We use multiple movies (rather than stuffing a whole project into one fat projector) in order to ensure scalability, clarity and reusability. The danger is that we then needlessly proliferate our assets by making more and more copies of them for each new movie.
    The idea of encapsulation can be extended to cover a projectís assets. If a particular asset is used across different modules it should be kept separate from each and linked into them (ëencapsulatingí the resource in one place). For example, if the same buttons are used across a whole project they should be kept in an external ëButtoní cast library which is then used by the movies that need those buttons. An obvious advantage of this is that we only have to edit this resource once to make changes throughout the whole project.Thissaves time and enforces consistency across a project.

    cast scripts vs. sprite scripts

    Director is a strongly object orientated system which means it is capable of being used to enforce encapsulation, scalability and many other aspects of good design. It is up to us to use this functionality. One aspect of this is that we should attatch scripts to cast members as member scripts only when we want the functionality of that cast member to be the same wherever it is used. If the functionality is to change depending on context we should not attach the script to the cast member but assign it to a sprite in the score. More accurately, any functionality that is context independant should be in the cast member script. Any that is context dependant should be in a sprite script. In this way, eg., a mouse up event is processed by the sprite script first to carry out context dependant tasks and then passed down to the cast member script to carry out general tasks.
    For example, if we have an ëupí button which takes the user to different places depending on the context, we should not have multiple copies of the button cast member each with different cast member scripts. Instead, encapsulation requires that we use the same bitmap in every place where we want the buttons to look identical but we attach different sprite scripts depending on context.

    Programming Conventions

    naming conventions

    It is useful if everyone writing code in a project follow some elementary naming conventions to help keep the code as comprehensible as possible.

    functional organisation of code

    It is important to organise code in a logical way. So all handlers relating to controlling a database should be kept together in their own script text and not mixed in with other handlers. This makes it easier to follow the execution of code and also, by breaking the code down into smaller sections, makes lingo execute more quickly.

    commenting code

    Code should be commented to make it comprehensible to anyone who is likely to have to support that code in the future. There is no need to comment and explain every line of code written but at least the purpose of handlers should be explained as should any unusual techniques used, or assumptions made by the programmer.

    documenting code

    Where we are producing Xobjects or objects that are to be used across a project, these should be clearly documented and an API specification produced so that others can easily call on the object in their own code.

    Programming Methodologies

    code encapsulation

    Wherever practical, code functionality should be encapsulated. On the largest scale this means that when we write a handler that performs a specific function the same copy of the handler should be called right across the project.
    For example, if we use a handler to control the display of QuickTime, rather than cut and paste this handler into every movie where we would like to use it we should either put the handler into a cast library that is shared by all the movies that need it or create a global object which encapsulates that code.
    To see why this is important, imagine that we want to change the way we control QuickTime, perhaps some amazing new QuickTime Xtra is released which we want to use, or perhaps we want to simply alter one line of code to make the QuickTime movie display better. If we have organised our code properly we can simply open one script text and edited it to incorporate the new functionality into our code. The changes made will be reflected consistently right across the project. The alternative is that we have to open up every movie and repaste all the changes or even modify the code by hand.

    object orientation (parent-child scripting)

    Object Orientated programming techniques are much talked about but hardly ever implemented. They are, however, very powerful and we should use them wherever appropriate. Basically, parent-child scripting allows us to create objects as global variables which embody a common functionality. This functionality is then available immediately to all the movies in a project.

    redundant and verbose code

    As a project progresses all redundant code should be stripped from it. This includes multiple copies of handlers, any code which has been commented out and any debugging code. At the same time, we should make sure code is as concise as possible. To give an example, I reproduce below some code which I found in a project we did for a major client

    Here is what it should look like with all redundancies removed


    The code below is easier to understand and will execute much more quickly.

    calling external movies

    During development we are invariably using *.DIR movies but before delivering the project all of these should have been turned into protected, *.DXR movies. Therefore, when calling in a movie we should not specify the extension, for example, by writing


    but instead should say


    The program will then call in either the DIR or DXR, as appropriate, so that during development it calls in the DIR
    while in the final version it launches the protected movie. This saves us having to rewrite any code and means we can test protected movies at any time during development without having to consider the code.

    relative addressing

    When calling other movies or external files we should always use relative addressing. Absolute addressing means that we use the full path name to the external file, for example


    Using this method of addressing means that when the project is installed on the userís machine the file ìsmovie1î will have to be in precisely the place specified in this line of code, otherwise the user will receive an error message. There is no reason why we should not allow the user to place our project anywhere they like (as long as they maintain the relative relations between files). For example, why shouldnít the user be able to move the whole project into a directory called ìmultimediaî ? In my own case, my home machine has three drives and I like to keep drive C: for system files. Why should we force people to install to a particular drive?
    As a matter of course we should always use relative addressing. For example, if the calling file in this case was in the directory ëc:\worktop\newProjí and was called orgMovie, we could call the same file using


    and then return to the calling movie using


    (assuming we donít use the ëplay movie ...í / ëplay doneí method). As long as we maintain the original directory structure, the root of the structure can now be moved to another drive or directory at any time.

    formal efficiency vs. real efficiency

    While we should make every attempt to make code as concise as possible, it is important not to confuse formal efficiency with real efficiency. For example, if we have some code


    It may seem more efficient to use


    since this is logically more elegant. However, this is only apparently more efficient since it means that Director has to recount the list every time it goes around the loop (and if there were thousands of items in the list this would be very inefficient indeed). This brings out the difference between formal (logical) efficiency and real efficiency, which takes into account how the Lingo interpreter actually works. The original method, which counted the list only once and held the result in a local variable is the more efficient.
    I used this example to illustrate a general principle about how to optimise code so I should point out that there is an easier way of rewriting this example in Lingo, namely


    Section Six : Optimising Performance


          ìSpeed provides the one genuinely modern pleasureî
       
      Aldous Huxley

    Introduction

    The following points simply indicate techniques and methods we can apply throughout the production process to really wring the last ounce of performance out of an application.

    Optimising during design

    These are specific points to be borne in mind in addition to the more general questions dealt with earlier.

    animation and digital video

    Keep on-screen animation to an absolute minimum whenever digital video is playing as the combination of the two can really exhaust a system.

    streamed media

    Wherever possible, keep the number of open, streamed files to a minimum as they too can really stretch system resources. This doesnít mean that we never have several such files running together, just that we should be aware of the extent that we are pushing the system at any time.

    Optimising during development

    These techniques should be applied throughout the course of a project.

    reducing colour depths

    Although we may have decided that a project should work in a certain colour depth, often it is possible to reduce the colour depth of particular graphics much further. For example, we may have a coloured line drawing or cartoon in 8 bit colour but which actually uses only one of the paletteís colours. In that case we can use the ëTransform Bitmapí option in Directorís ëModifyí menu to dither the colour down to 1 bit (if the graphic is not black, convert it to black before doing this then, after converting it, select the graphic in the score and use the Tool Palette to change back to the original colour). The graphic will then be one eighth the size and will load eight times faster.
    In some cases it may even be worth turning an 8 bit or higher image into several 1 bit images. For example, if the original image is 8 bit but only uses two colours, then it is still worth turning this into two overlaid 1 bit images, with the saving in bit depth more than making up for the doubling in the total size of the images.

    editing cast members

    All graphic cast members should be edited down to the size of the minimum bounding box of the significant area of the graphic. That is, if a graphic shows a logo cropped from against a background image and is going to be placed over the raw background itself, then as much of the background as possible should be cropped from the logo.
    Similarly, an irregularly shaped graphic can often be split into several much smaller rectangles whose total area is far less than that of the original image. This can be done very easily. Say that we want to split an irregularly shaped graphic into three to save space. Simply make two more copies of the original graphic in the cast (hilight the cast member and press CTRL-D twice) then cut and paste the sprite corresponding to the image on top of itself twice in the score. Next, edit each of the three cast members to split the image into three component parts, then select each member along with each of the three sprites in turn and press CTRL-E to perform a cast member substitution. Each of the three parts of the image will now be perfectly aligned on the stage.
    A good example of when this technique comes in useful is when we use a rectangular frame around some part of the stage. This can very easily be split into four parts (top, bottom, left and right frames) which together are far smaller than the original graphic.

    removing redundant casts

    It is imperative that all redundant cast members should be removed from a project when they are no longer needed. If this is not done at the time they become redundant the cast libraries end up peppered with members which no longer need to be there. At the end of the project it is often too late to remember which members are no longer needed (even using CTRL-; and asking for a list of members not used in the score will not tell you which of these are puppeted onto the stage).

    using tiles

    Patterned backgrounds can often be replaced with tiles, saving a great deal of space. Although we do not use such simple patterns very often, this is actually a very effective way of producing backgrounds. It is especially recommended in Shockwave movies where size is at an even greater premium.

    using inks

    When Director is redrawing a frame (every time it goes to the frame, or when an updateStage command is issued), the use of certain inks makes the whole redraw process much slower. Copy ink is fastest, with Matte and Background Transparent being slower, and Blend is extremely slow. Obviously there are some trade-offs to be made here.
    A good example of where we can increase performance is when we have a large graphic which we have made Matte because we trimmed part of the background away leaving it as an irregular shape (and so if it was Copy there would be unwanted white space on stage). It is much better to leave the graphic as a rectangle and use the Copy ink, since the graphic is stored as a rectangular image anyway, so trimming irregular shapes from it doesnít decrease the size (only cutting down the area of the bounding box reduces the actual size). The combination of a rectangular shaped graphic and Copy ink is the same size on the disk and is much quicker to draw than an irregularly shaped graphic with Matte ink.

    stretched sprites

    Stretched sprites also take far more time to process than sprites set to the actual size of the cast member. Depending on circumstances, we may get better performance by using the ëAuto Distortí tools in the Xtras menu to create a series of intermediate sized bitmaps which can be preloaded and then used to create the same effect as stretching. To make a sprite the same size as its cast member select the sprite properties and click ëRevertí.

    digital video

    QuickTime (which is generally what we are talking about in a project when we say ëdigital videoí) is always played ëdirect to stageí in Director for Windows. On the Mac, however, it can have sprites placed on top of it. Because QuickTime plays much faster when it is projected direct to the screen, unless we need to have sprites above the QuickTime sprite we should make sure that the QuickTime member is set to display ëDirect to Stageí. This can be done by changing the properties of the member (either right click on the cast member - oh, I forgot, you are using a Mac mouse - OK, try highlighting the member and then either clicking on the Information icon at the top of the cast window or pressing CTRL-I and selecting ëDirect to Stageí).
    Digital video plays much slower when stretched. Make sure that all digital video sprites are set to the actual size of the videos or, if this really isnít possible, select the properties of the member again and set it to crop the picture rather than stretch it.

    importing audio

    Where the playing of audio is causing a performance problem it is worth remembering that linked audio loads more slowly than imported audio. Therefore, it is worth considering importing the sound into a cast library. If the sound is used by several movies then you can import it into an external library and use it in all movies that need it (despite being in an external library, the sound will still load better than if it is played as a linked file).

    using variables

    It is not unknown for people to write data into a text field then read it back later down the line rather than use a global variable or pass the value as a parameter to another handler. This is an absurdly slow way of handling data (Lingo handles text more slowly than any other data type anyway, and when it has to read and write to a field as well the performance drops right down). Always use variables in memory (global or local, as appropriate) rather than writing to fields.

    cast reference by index and by name

    If you are going to repeatedly refer to a particular cast member, refer to it by number (called ëreference by indexí) rather than by name. If you refer to a member by name Director has to trawl through all itís casts looking for it. It is much more efficient to set up a global variable which you can then refer to in your handlers. For example


    and then later you can say, eg.


    (this code relies on functions made available by the MPEG Xtra). Whether it is worth doing this depends on how often a particular cast member is going to be referred to in the course of running a program. If it is only referred to once, then the method I have outlined actually wastes a little (though practically negligible) bit of time since the movie is looked up by name once in this method anyway, plus you have the slight overhead of reading the global when you finally come to address the member. However, if a cast member is going to be referred to repeatedly in the course of a program it is worth initialising itís address in this way.
    If you need to refer to a large number of cast members like this it may be worth setting up a property list global instead with the name of the members you want to index used as property names, and the index references of the members as the values.

    clearing global variables

    To free up memory resources it is good practice to clear any global variables by resetting them to 0 or EMPTY when you have finished using them. For debugging reasons, it is also a good idea to include the command clearGlobals in the stopmovie handler to make sure that your globals are being initialised properly when you run the movie.

    opening and closing objects

    Leaving a movie does not kill any global objects created by that movie - that is part of the power of parent-child scripting ; you can create an object in one movie which is available to any other movie when it is opened. Make sure, then, that if you have finished with an object you kill it by setting the global that refers to it to 0 or EMPTY. Eg.


    This releases the system resources used by the object (which can be quite considerable with some objects).

    using updateStage

    It is usual during development to end up with redundant updateStage messages littering the code. This is because it is easy to keep inserting the command into the code just to make sure that all the changes you have programmed are reflected on stage. However, updateStage is an extremely resource-hungry command, since it forces Director to redraw the whole of the stage whether it needs to do so or not.
    Therefore it is important that every single updateStage command is justified and that any superfluous calls to it are removed.

    Optimising before delivery

    compacting movies

    Every movie in a project should be protected, turning it from a *.DIR into a *.DXR.

    To protect a movie select ëXtrasí, then ëUpdate Moviesí, then select ëProtectí and ëBackup Into Folderí.

    remove debugging statements

    Debugging statements slow down performance of your code, especially those which put a value into the watch window. Remove all debugging statements before final shipping.

    memory management strategies

    It is possible to carefully manage the way Director loads and unloads cast members from memory using the Lingo commands idleLoad, preLoad, unLoad, preLoadMember, unLoadMember, preLoadMovie and unLoadMovie, and or by setting the properties of cast libraries or individual cast members either via menus or dynamically, setting the properties the preLoadMember using Lingo.
    During the Optimisation phase of a project we should run every movie in a project and work out how we can use memory management to overcome any performance bottlenecks. For example, if a particular frame is very slow to load, we may be able to preload it while the user is looking at the previous screen, using


    where ënextFrameí is the marker of the slow frame. This will load the cast members in all the frames between the current frame and the target frame. To load just the target frame, use


    You could preload an animated scene by putting markers on the first and last frame of the sequence and preloading them using this command
    Individual cast members can be preloaded using, eg.

    Individual cast members can be preloaded using, eg.,


    Even if we cannot optimise the whole project completely we can at least get rid of the worst bottlenecks using these techniques.


    Section Seven : Conclusions

    As is inevitable in an exercise of this kind conventions and methods which seem straightforward on paper turn out to be harder to apply in the real world. Real world applications often require that, for good reasons, some of the usual rules should be ignored. Once again, in concrete situations some of these guidelines will conflict.
    George Orwell once wrote an essay on good grammar and writing style but finished by telling the reader to ëbreak any of these rules sooner than do anything barbarousí. The same applies with multimedia - the guide lays down some conventions which we should always use but the general methods and heuristics it describes can help us address our production problems only if they are used creatively. In other words, ignore any of the rules laid down here rather than do something barbarous.
    Still, the main reason many of the techniques here will sometimes be ignored will inevitably be because of the pressure of deadlines. Of course we always want to keep the client happy, which can mean making all sorts of last minute modifications to a project, and sometimes we are still building core elements of the program at the last minute because we miscalculated how long the project would take. However, we should remember;

  • First, although it is always difficult to predict just how long a project will take to implement (often it takes half as long or twice as long as planned) our only weapon against this is better project planning.
  • Second, every time we cobble together part of a project without building it properly we are not really doing the client any favours - the new work will not be optimised properly, it may not work as specified, it may interfere with the behaviour of the rest of the program, the program will be harder to maintain in the future, future expansion will take longer than if it had been built properly and so on. These are all excellent reasons to resist the temptation to build sloppily in the first place.
  • Finally, Iíd like to point out in advance that the following excuses will not be accepted under any circumstances;

    -
    Andy Wilson
    1996