Tutorial: Jigsaw using ActionScript 3.0.

anthropologistbarrenSoftware and s/w Development

Jul 4, 2012 (5 years and 2 months ago)

288 views

Tutorial:
Jigsaw
using ActionScript 3.0.


This tutorial describes how to build a computer implementation of
a jigsaw puzzle.
It will
demonstrate the use of classes, packages, objects and separate .as files.


Applications

I prepared three versions of the j
igsaw
. The openin
g screen of the first version would be
something like this (I say 'something like', because the pieces are mixed up by a random
process and, presumably, would look different each time):




Notice that it has 3 buttons. The player moves p
ieces by pressing the mouse button
down, dragging the piece by moving the mouse, and dropping/releasing control by
releasing the button. The player can rotate a piece by pressing the mouse button down
and using the left and right arrow keys. The player ch
ecks if the puzzle is done by
clicking on the Check button.
The next screen shot shows the result of clicking on the
Build button and then clicking the Check button.




The next shows the result of clicking on Check at a different time:




The next versi
on of my jigsaw does away with the Check button and incorporates
automatic checking whenever the player releases the mouse button. Here is the opening
screen:




The next screen shot shows the puzzle after the program has determined that it is done:




N
ote that checking for completion in both programs is done with a tolerance factor: the
player does not have to be perfect. If you want to make the puzzle more challenging, you
can decrease this factor. If you require the player to position things exactly t
o the pixel, it
will be very difficult to complete.


The third version of the jigsaw has something called an attractor or idler. The game
begins with the pieces periodically in new, mixed up positions. When the player starts to
drag a piece or clicks on
a button, the pieces stop moving. If the player does not do
anything for a certain period of time, the pieces move again. The idea here is that this
application could run on a kiosk and 'attract' people passing by. The term idler comes
from the notion t
hat the game is idling. People build idler/attractors that have no
connection to the actual application. For jigsaw, mixing up the pieces is an obvious
choice for the idling display.

Overview

The critical parts of building this application are



creating th
e puzzle pieces, including determining the information that needs to be
stored in order to re
-
create the puzzle



using the ActionScript 3.0 constructs of class and package to
defin
e
a class,
named Piece, that will specify Piece objects as well as class meth
ods (
build
,
mixup
and
checkit
)



creating the .fla file, with the piece movie clips and frame
code, which
will make
reference to a package and a class, and also contain buttons and a text field.


You will create the puzzle pieces by taking an image and effe
ctively slicing it up. You
move the pieces so that the individual registration point/transformation point is close to
the middle of the piece and not where the registration point or transformation point was
for the original whole image. Because we (the cod
e) needs to be able to put the pieces
together and also check if the pieces are close enough to consider the puzzle done, you
need to record coordinate information. The exact procedure is described below.


Note that the checking method does not require th
e pieces to go in the same position but
just be correct (close to correct) relative to each other. Putting this another way, the
puzzle can be put together with the top left corner NOT at the top of the screen. Check
out the last screen shot to see this.


The coordinate information, referred to here as
offsetx
and
offsety
, needs to be
bundled together with the movie clip instance itself for each piece. This is a perfect
application of class and objects.
Classes are ways to define new types of values.
The
y are
a way to put together data (variables) and functions (called methods). You have seen
these in action for built
-
in classes whenever you see the dot notation.
I haven't used it in
these tutorials, but perhaps you know from JavaScript about
Date
object
s. In
ActionScript, we have movie clip objects. Objects
have
properties, also called attributes,
and also methods
, functions that work with and on the object attributes
. Recalling the
target movie clip instance in cannonball, I used the code


target.gotoA
ndPlay(2);


This was making use of the
gotoAndPlay
method of the target object. The movie clip
class also set up attributes for each object, for example,
x
,
y
,
rotation
, and
visible
. There also are classes that contain methods and variables for the whole c
lass,
not for individual objects of the class. The important example of this is the
Math
class
and class methods such as
random
and
floor
and class variables such as
PI
.


Programmers in ActionScript can define their own objects. The terminology
/format
is
as
follows: you define a class



modifier
class classname {


For any class variables:

modifier static var variable_name:datatype;


For the
object variables

modifier var variable_name:datatype;



For the class methods

modif
ier static function method_name ( ) { }

For the object methods


modifier function method_name( ) { }


one of the methods, which would have the same name as the classname, is the

constructor: the method called w
hen a new object of the class is created.

}


[Note: you do not need to follow a strict order and you can mix these different categories
up.]


The modifiers signify how/where the function can be called or the variable referenced.
This is done to do what i
s called information hiding. It isn't really to hide things but to
make it easier to find errors and debug code. If the exact details of some implementation
are confined to one place, it will be easier to make changes.
For this example, certain
things wil
l have the modifier
public
indicating that they can be used outside of the
class and others will have the modifier
internal
meaning that they will only be used
inside the class. There are two other possibilities, but I won't get into that here.


Here is
some of the code (the whole thing is given below) for the class Piece:

public class Piece {

internal var offsetx: Number;

internal var offsety: Number;

internal var mclip:MovieClip;


public function Piece (xx, yy, clip) {


this.offsetx = xx;

this.offsety = yy;

this.mclip = clip;

}


}


To create an object of class
Piece
, I use statements such as



var p1:Piece = new Piece(41.6,48.1,piece1);


This will
set up an object of type
Piece
and

invoke the function named
Piece

to set
the object variables to hold
the coordinates and
a reference to
the movie clip instance.


There are 3 functions that I need to use that do not apply to individual
Piece
objects but
to all the objects. These are for b
uilding a complete puzzle, mixing up the puzzle pieces
randomly on the screen and checking if the pieces have been put together reasonably
correctly. There probably are many ways to do this. What I did was to set up a class
variable that was an array hold
ing all the Piece objects and three class methods:
buildit
,
mixup
and
checkit
.


internal static var pieces:Array = new Array();


The constructor function
Piece
includes a statement that adds the newly constructed
Piece
object to this array. The
buildit
,
mixup
and
checkit
functions make use
of pieces.


Class definitions are contained in packages. Specifically, each class definition is in its
own file and the contents of the file are


package jigsaw {

class Piece {



}

}

The example here has just one
class and, therefore, just one file:
Piece.as
. It MUST
go in a folder named
jigsaw
and I placed it in a folder I named
as3
directly in my C
drive. See below concerning the specification of the
classpath
that indicates to the
Flash environment where the p
ackages are located.


The code interprets the key stroke event using built
-
in variables.

Implementation

You need to prepare two files for this application:
the
.fla
file and
the
.as
file that
holds the package that holds the
Piece
definition. The name of
the
.as
file must be
Piece.as
. It needs to go in a folder with the same name as the package, namely
jigsaw
, and the
jigsaw
folder must be in a folder named in the
classpath
list. I
will give instructions on this later.


Start by
opening up the Flash env
ironment, under Create New, click on Flash File
(ActionScript 3.0)




Using the Web or some other program, copy an image to the Clipboard. Back in Flash,
click on Insert/New Symbol/ and, making sure that Movie clip is selected, give the
symbol the name
ba
se
. In the panel, click on Edit/Paste. If the image is too big,
reduce
the size using Transform/Scale or the width and height on the Property panel.
The screen
shot below shows an image I used Scale on (moving in from the corners) to make be
under 550 by
450 in size. By using Scale and the arrows, I kept the proportions (aspect
ratio). I also moved the image so that its origin is at the upper left corner.







Making sure the whole image is selected, click on Modify/Break apart. This turns the
intact i
mage into something you can slice up. You should see
something like the screen
shot below, with the pixels in the image selected.




Sometimes it is necessary to do Modify/Break Apart a second time. You now use the
pencil tool or the straight line tool
to slice up the picture. The screen shot below shows
the result of using the pencil, with the smooth option (in between straighten and ink) to
draw a curve and then using the arrow to select the cut
-
out part.




Use this method to 'slice up' the picture.





Then,
do the following for each piece. Select one piece




and then click on Edit/Copy. Then Insert/New Symbol. Make sure the movie clip option
is selected, and give the pieces the names piece1, piece2, etc.
Click on Edit/Paste in
Place. Go to Wi
ndow/Info to
make the info panel appear. Make sure that in the Info
panel the graphic in the middle shows 3 squares and a circle in the lower right. This
indicates the transformation point.



The print is small, but notice in my example the numbers for
X and Y: 68.5 and 81.3.
For
each of your pieces,
WRITE DOWN piece1 and
the
two numbers
on paper or using a
reliable on
-
line note pad
. Then change the numbers to 0 and 0.

You will see your piece jump so that the cross hairs are
more towards the middle
.




Continue with all the pieces OR you can do one or two more and go on to do the rest of
the application and then come back.


Bring

each piece to the Stage and give each piece an instance name: use piece1, piece2,
etc.


Rename the first layer
board
. Add a
new layer and call it
actions
. Add a third layer
and call it
interactions
. The interactions layer will be above the board layer,
meaning that what you are about to put on it will be above any pieces. Add 3 buttons and
one dynamic text field using the tec
hniques you have learned from the other tutorials.
Name the buttons:
buildb
tn
,
mixupbtn
and
check
btn
and name the text field
result
. The screen shot shows my lizardplain application after this has been done (and
also after code has been put in the actions
layer, which I have not shown you yet).




Click on the actions layer and Window/Actions to open up the Actions panel. Write as
the first line:


import jigsaw.*;


These are instructions to the Flash environment to import everything in the jigsaw
package.
Since there is only one thing, one class, the Piece class, this statement has the
same effect as writing


Import jigsaw.Piece;


You will see later how to let Flash know where to find this package.


The next part of the code is setting up the objects tha
t hold the offset information and a
referen
ce to the movie clip instance. I haven't told you the specifics of
Piece
yet, but it
will be available (in the
jigsaw
package). Here is my code for the lizard puzzle. The
numbers here are the numbers you wrote do
wn from the Info panel for each piece.


var p1:Piece = new Piece(41.6,48.1,piece1);

var p2:Piece = new Piece(101.5,48.5,piece2);

var p3:Piece = new Piece(169.0,39.5,piece3);

var p4:Piece = new Piece(42.0,110.5,piece4);

var p5:Piece = new Piece(111.0,122.5,
piece5);

var p6:Piece = new Piece(179.6,111.5,piece6);


Again, you can do just 2 or 3 and wait to do the rest or you can do them all now.


The next 3 statements should be familiar to you from the other tutorials. You will set up
the event handling for the
3 buttons. The functions invoked here are class methods (static
methods) of the
Piece
class. I haven't shown you that code yet. That comes soon.


mixupbtn.addEventListener(MouseEvent.CLICK,


function(ev) {Piece.mixup();}


);


buildbtn.addEventLis
tener(MouseEvent.CLICK,


function(ev) {Piece.buildit();}




);


checkbtn.addEventListener(MouseEvent.CLICK,


function(ev) {


var res:Boolean;


res = Piece.checkit();


if (res) {


result.text = "G
ood job!";

}


else {result.text = "Keep working.";}}


);


I want the puzzle to start with the pieces mixed up, so I put in a call to the
mixup

method.


Piece.mixup();


Lastly, I put very brief instructions into the
result
text field.


result.text
="Use mouse to drag&drop. With mouse down, use
arrows to rotate"


Now let's go on to the .as file. Click on File/New and then select ActionScript File.




The code
is a definition of the
Piece
class in the package
jigsaw
. There could be
other files with
other classes, but for this application, there is just this one file. The
outline is


package jigsaw {


import statements indicating what parts of Flash are needed.


public class Piece {


definition of class variables, object variables, class meth
ods and object variables


}


}


There are 3 import statements needed:



import flash.display.*;


import flash.events.*;


import flash.ui.Keyboard;


You may ask: why do we need this? You might accept that it is necessary to indicate in
the .fla
ActionScript the need for the jigsaw package, but why is it necessary to indicate
that I need
specific
stuff in Flash. The answer is that requiring the import statements
prevents certain errors such as referencing a built
-
in thing when you actually meant
a
programmer defined thing. It also may make compilation go quicker.
If you imported
class definitions that you actually did not use, this would not
increase
the size of the
published files.


In ActionScript, you can define something to be a constant by
using
const
in place of
var
. This means that if the code assigns a value to it, this will be caught as an error. By
custom, the names of constants are all caps. I use this for the numbers specifying how
much to rotate the movie clip instance for each arro
w key stroke.


The coding in Piece.as includes
addEventListener
statements.


Here are the entire contents of the file named Piece.as.


package jigsaw{

Start
package

import flash.display.*;

Import display

import flash.events.*;

Events

impor
t flash.ui.Keyboard;

Keyboard



public class Piece {

Start class definition of Piece

internal static var
pieces:Array = new Array();

This will hold all the pieces

internal static const ROTUNIT=
15;

Defines amount of 1 rotation


internal static const ROTNUM =
24;

How many rotations in a
circle

internal static var
dragging:Boolean = false;

Indicates if a piece is being
dragged



internal var offsetx:Number =
0;

Object variable

internal var offsety:Number
=
0;

Object variable

internal var mclip:MovieClip;

Object variable: points to the
actual movie clip instance



public function Piece(xx,

Starts constructor for a piece

yy,


clip) {


this.offsetx = xx;

Sets object variables

this.offsety = yy;


this.mclip = clip;


Piece.pieces.push(this);

Adds to pieces array


clip.addEventListener(MouseEvent.MOUS
E_DOWN, startdragging);

Sets up for mouse
events


clip.addEventListener(MouseEvent.MOUS
E_UP, stopdragging);



clip.addEventListener(KeyboardEvent.K
EY_DOWN,reportKeyDown);

Sets up for keyboard event

clip.buttonMode = true;

Sets up so movie clip can
get
mouse events and k
ey events

}


internal function
startdragging(ev) {

Object method

this.mclip.startDrag();


dragging = true;


}


internal function
reportKeyDown(ev) {

Object method

if (dragging) {


if
(e
v.keyCode==Keyboard.RIGHT) {


this.mclip.rotation +=
ROTUNIT;


}


if
(ev.keyCode==Keyboard.LEFT) {


this.mclip.rotation
-
=
ROTUNIT;


}

Close if

}

Close if dragging

}

Cl
ose reportKeyDown method

internal function
stopdragging(ev) {

Object method

dragging = false;


this.mclip.stopDrag();


}


public static function
buildit() {

Class method

var i:int;


var np:Piece;


for (i=0;
i<Piece.pieces.length; i++) {

For each of the pieces

np=pieces[i];

Extract the i
th
piece and

np.mclip.x = np.offsetx;

Position in x

np.mclip.y = np.offsety;

Position in y

np.mcl
ip.rotation = 0;

Set rotation to 0

}

Close for

}

Close function

public static function mixup()
{

Class method

var i:int;


var np:Piece;


for (i=0;
i<Piece.pieces.length; i++) {

For each piece


np=pieces[i];

Extract piece

np.mclip.x =
Math.floor(Math.random()*400);

Position randomly in x

np.mclip.y =
Math.floor(Math.random()*400);

Position randomly in y

np.mclip.rotation =
ROTUNIT*(Math.floor(Math.rand
om()*ROT
NUM));

Rotate randomly

}

Close for

}

Close mixup method

public static function
checkit():Boolean {

Class method. Returns false
for not done or true for okay.

var tolerance = 20;

You may reset this if you
want more
challenge

var diffx0:Number;


var diffy0:Number;


var diffx:Number;


var diffy:Number;


var i:int;


var np:Piece;


var np0:Piece = pieces[0];


for (i=0;
i<Piece.pieces.length;
i++) {

For all the pieces, compares
the differences with the offset
values with the differences of
the first piece and its offsets

np=pieces[i];


diffx0 = np0.offsetx
-

np.offsetx;


diffy0 = np0.offsety
-

np.offsety;


diffx = np0.mclip.x
-

np.mclip.x;


diffy = np0.mclip.y
-
np.mclip.y;


if ((Math.abs(diffx
-
diffx0)>tolerance || Math.abs(diffy
-
diffy0)>tolerance)) {


return false;


}

Close if


if
Compares rotations to 0

(Math.abs(np.mclip.rotation)>=
ROTUNIT) {

return false;


}

Close if

}

Close for loop

return true;


}

Close
checkit
method

}

Close class definition

}

Close package


CAUTION:
The location of package folders appears to be a delicate
matter
.
The following works on my home computer. See below for instructions for the
computer classroom.

The name of the package must match where it resides in the
computer file structure. I
constructed a new folder 'right below' c: called
as3
and created
a new folder in it called
jigsaw
. (I used as3 for all my ActionScript packages.) See
the
location of
as3
and
jigsaw
in the following screen shot.




Now that you have saved the
Piece.as
fil
e in a folder named
jigsaw
, you need to go
back to the
.fla
file to let Flash know where to find the package. This is called setting
the
classpath
. Click on File/Publish Settings and then Flash, and then next to
ActionScript 3.0, the Setting button. Then
next to classpath, click on the cross
-
hairs in a
circle to get a browse window. Click on the folde
r holding the package folder (the parent
folder of jigsaw).




Spring 2008, Purchase College NS1013 computer lab of PCs: create a new folder called
as3 on t
he D drive, create a new folder called jigsaw (the name of the package), and put
the file Piece.as in this folder. In Flash, for the .fla file, under Publish Settings, browse to
D:
\
as3 and click ok to make that the Classpath.


You now can test the program.
First save the .fla file. This can be saved anywhere. I
saved it as lizardplain. Then, in the usual way, click Control/Test Movie.


Changes for the automatic checking


Now the question is how to implement automatic checking? One aspect of this was easy
a
nd another turned out to be more difficult than I initially expected. The first steps are
easy: delete the button labeled
check
and remove the corresponding
addEventListener
statement. Change the first statement to be


import jigsawauto.*;


I renamed the
Text Field
instructions
. This was not necessary, but I thought it was
a better name since that is how the field is used initially.


Save the .fla file as
lizardauto.fla
. This can be saved in the same folder as
lizardplain.fla
.


Next, open up the
Piece.a
s
file. I then saved this file by going to c:
\
as3 and creating a
new folder called
jigsawauto
. Save
Piece.as
in this folder. Note that this means
you do not need to change or add to the classpath for
lizardauto
. It is the same as
lizardplain
. [Of course
, I am not forcing the name lizard on you. You can name the
.fla file whatever you want. Since, hopefully, your initial one is working, I would save
the new one with a different name.]


This code refers to the TextField datatype, so you need to add the st
atement


import flash.text.*;


to the import statements at the start of the Piece file.


In the Piece.as file, look at the stopdragging method. This is where I will put the code to
call
checkit
. I change the header for checkit to have the internal modif
ier, since it is
no longer called from outside the class.

internal static function checkit():Boolean {


The idea that did not work was to have the
stopdragging
method create a Text Field
dynamically. This is possible, but it is necessary to do what is ca
lled add the Text Field to
the display list and there is not a good candidate. This is chiefly for security reasons. So
in order to provide a place to write the "Good Job", what I do is have the
mixup
method
pass in the name of the text field already on
the board:



Piece.mixup(instructions);

instructions.text=

"Use mouse to drag&drop. With mouse down, use arrows to rotate"


When you make this change, be sure and save the .fla file again.


Now, back to
Piece.as
, add a new class variable:


internal static
var res:TextField;


Change the header and the statement to
mixup
:


public static function mixup(t:TextField) {









Piece.res = t;



The mixup function also is called during the program as a result of the event of the mix
up button being pressed. This
means that you must change the addEventListener call


mixupbtn.addEventListener(MouseEvent.CLICK,


function(ev) {Piece.mixup(
instructions
);}


);




The
res
class variable
will be re
-
set to the same thing every time
mixup
is called, but
that is oka
y.
It happens at least once. The modified definition of the method
stopdragging
is the following:


internal function stopdragging(ev) {




dragging = false;




this.mclip.stopDrag();




if (checkit()) {





Piece.res.text = "All Done!";




}



}


This 's
ays' if
checkit
returns true, change the text in the text field pointed to by the
class variable
res
to show "All Done!" If the method does not return true, do nothing.
That is, don't tell the player to keep working.


Note: the use of
Piece
is optional
within the class, so I could omit it before the
res
and
I could add it before
checkit
.


Save the file as
Piece.as
in the
jigsawauto
folder. Test the program.


When you publish the program for uploading to the web, you upload the .html and the
.swf file
.
As before,

you need to upload a file named
AC_RunActiveContent.js
to the file
folder, if that is not already present. This file is created by the Flash environment and will
be in the folder with the other files.


Changes for idler/attractor

This applicati
on has 2 stages: idling and not idling. During idling, there is a timing event
with a short time interval. During not idling, the event is harder to describe. It is the
event of nothing happening. This is how I think about it: do you even set an alarm cl
ock
and then decide, BEFORE it goes off, to push it further ahead. Say it is set for 8am. You
wake up at 7:30 and decide you need at least another hour of sleep, so set the alarm for
8:30. You wake up at 8:15, decide you want at least one more hour, so se
t the alarm for
9:15. This is how I handle the funny event of nothing happening. I will write code that
stops a time and then starts it anew. If the timing event actually occurs, it does so
because it has been allowed to get to the end of an interval.


S
tart by creating a new folder in the parent director of the jigsaw and jigsawauto folders
and name it jigsawidler. In Piece.as, change the name of the package to jigsawidler and
save it in the jigsawidler folder. You will be making more changes. Go to t
he .fla file
and change the name of the file to lizardidler and save it. You will be making more
changes here as well. It is my practice to do this right away to avoid
saving on top of a
working program.


Back to the Piece.as file (in the jigsawidler fold
er): here is my strategy. I
will have
two
timers:
shorttimer
with an interval of 1 second and
longtimer
with an interval of
20 seconds.
I need to add to the
import
statements. They now are:


import flash.display.*;


import flash.events.*;


import flash.ui.
Keyboard;


import flash.text.*;


import flash.utils.Timer;


The timer objects are class variables and not accessed outside of the Piece coding so the
modifiers are static and internal:


internal static var shorttimer:Timer = new Timer(1000);

internal
static var longtimer:Timer = new Timer(20000);


I define 2 new class (static) functions.
One,
idler
, calls
mixup
and does things with
the timers. Both the timers set up (the term register is used)
idler
as the event handler.
The other,
setups
, is used on
e
-
time
-
only to send the text field
AND something I will
describe soon
. I could have
used such a function in the jigsawauto game
. I needed to do it
now because of the requirements for event handlers to have one argument being an event.

I changed
mixup
to
NOT have any arguments and NOT have the line setting
Piece.res
.





The idler function is:


public static function idler (ev) {


// only one timer actually will be going



longtimer.stop();



shorttimer.stop();



Piece.mixup();



shorttimer.start();


}


No
w the challenge is to find a place to set up (register) the timing events. I decided to do
it
in the same function used to get the text field address 'over' to where the Piece class
instances could use id. The new function to accomplish the task for settin
g up the text
field to be used to display All Done and register the timing events is:


public static function
setups
(t:TextField) {


Piece.res = t;


shorttimer.addEventListener(TimerEvent.TIMER,Piece.idler);


longtimer.addEventListener(TimerEvent.TIMER,Pi
ece.idler);

}


I added the following two statements to each of the
startdragging
,
buildit
and
mixup
functions.


shorttimer.stop();



longtimer.stop();


There apparently is no harm in stopping a timer that is not started. This greatly simplifies
the coding.
It is possible to access the status of a timer, but it is not necessary here.


The
stopdragging
function is the one to start the
longtimer
. Add this one
statement:

longtimer.start();


This one requires patience to test! Be sure both files are saved (and
that the .fla file has

import jigsawidler.*;


and the Piece.js file starts with



package jigsawidler {

ActionScript 2.0 to ActionScript 3.0


Only read this if you are familiar with previous versions of Flash and want to reflect on
the differences
.


As I say in all these tutorials
, consider that much is the same: you
still need to work with
the base image
and
write down coordinates to be used for the
offsetx
and
offsety

values. What is different is how this information is associated with the piece
.

Y
ou need to
set up buttons, and you need to set up events and write code for event handling for mouse
actions and for key presses. Second, please appreciate the fact that creating the separate
Piece files in the
jigsaw
and
jigsawauto
folders means that y
ou can produce
new
jigsaw puzzles quickly.
You do not copy code but use the very same files.


Beforehand the offset data was associated with the pieces as part of the frame code of a
movie clip symbol. When that proved difficult to do in ActionScript 3.0
, I decided to use
objects. I worked to make the interactions and the specifics of each
jigsaw
puzzle part of
the .fla file and the general stuff concerning
how jigsaw puzzles work
part of the Piece.as
files.
The created a small challenge when I wanted t
o put the generation of the All Done
message into the Piece code, but I solved it by passing a reference to the text field.


This application demonstrates what is termed the
composition
relation between objects:
the movie clip symbol instances that are t
he pieces are referenced as object variables in
the Piece object. In other applications (for example, bouncing things), you will see
another type of relationship of objects, specifically
inheritance
.


The idler/attractor jigsaw made use of the
Timer
class.
This implementation seems
simpler to me, but I haven't really gone back to study the older versions. Setting up the
two timers and thinking about having two alarm clocks that didn't 'mind' being turned off
even if they were off, helped me.
Note that cre
ating a
Timer
does involve adding more
to an application than using multiple frames or the
Enter_Frame
event. For this
application, I did use 2
Timer
objects. It is possible to change the timing interval. The
attribute is named
delay
, so instead of defi
ning two timers, I could have declared just
one, call it
mytimer
, and had code



mytimer.delay = 1000;


and


mytimer.delay = 20000;



My not so economical approach appears to be acceptable.

Please send comments and suggestions.