ActionScript 3.0 Tutorial for the pub game Spoof
This version of the pub game of Spoof has two steps: the player chooses from 0, 1, 2, or
3 "coins". The choices are meant to indicate the number of coins in your pocket. The
choice of 3 is 3 or more. The computer program randomly picks from the same choices.
The sum of these two quantities is determined. The 2nd step has the player guessing at
what this sum is. The computer program randomly picks another number. In this
implementation, this amount is among feasible choices: the computer 'knows' the sum is
at least what the computer pick is. The computer guess cannot be the same as the player
guess. The program then checks to see if either guess was correct.
As is my practice, I implemented the game in a simpler version and then in a more
complex version keeping score. In the first version, the game does not end and, in fact,
you can cheat and guess again after being told the answer. This had the benefit of
allowing me to test certain features of the game. In the second version, the program
shows the results, puts crosses on the screen for the player or the computer wins, and, if
player or computer has not won 3 times, goes back to frame 1 for a new round.
Basic game
The steps are implemented by two frames. The first frame is
The brown boxes are buttons. When the choice is made, the program makes a random
choice. The event handler (the function registered for these buttons) makes this choice,
computes the sum, and then goes on to the 2nd frame.
The action now is for the player to make a guess using the radio buttons and then clicking
on My guess. The event handling is a function that determines the radiobutton clicked,
makes a guess for the computer, and then checks to see if either is correct. The answer is
displayed in the text field.
You build this application by creating the 4 buttons (Insert/New Symbol…. Pick the
button option and give each button a name. After creating the first button, I left-clicked
to create duplicates to be sure to get the buttons the same shape. Bring an instance of each
button to the Stage and give each an instance name. Place a static text field on the Stage
to give directions.
I renamed the first layer board and added a new layer called actions. This is just to make
things organized. The benefits of this are realized in larger applications. In the first frame,
actions layer, click on Window and open the Actions panel.
The code for this frame does the following: register with each of the buttons a call to the
function playgame with parameter corresponding to the appropriate value. Include the
var statements for the global variables. Then define the function playgame. Lastly,
include a stop(); statement so the program does not advance to the second frame.
Here is the code:
nocoinbtn.addEventListener(MouseEvent.CLICK, function (ev)
{
playgame(0); });
onecoinbtn.addEventListener(MouseEvent.CLICK, function (ev)
{
playgame(1); });
twocoinbtn.addEventListener(MouseEvent.CLICK, function (ev)
{
playgame(2); });
manycoinbtn.addEventListener(MouseEvent.CLICK, function
(ev) {
playgame(3); });
var playerscoins:int;
var playersguess:int;
var pcguess:int;
var pcscoins:int;
var sum:int;
function playgame(player) {
playerscoins = player;
pcscoins = Math.floor(Math.random()*4);
sum = pcscoins + playerscoins;
gotoAndPlay("guessing");
}
stop();
Insert/Timeline/Keyframes on both layers. It does not matter which one: click on either
layer and give a Frame label (Properties panel): guessing. Actually, you can make
this a blank keyframe. In any case, on the board layer, erase everything. Use the T tool to
create one static keyframe with directions (see example). Create a dynamic text field and
give it the instance name res. Click on Window/Components and select radiobutton.
Move 7 of these buttons to the Stage. Using the Parameters panel (Click on
Window/Properties and then Parameters to make this visibile), set up the label for each
button and to set each of the buttons to be the same group: guesses. ( NOTE: I could
not get value to work, so I used the label to get the value I needed.)
By the way, you can use the X: and Y: values to make the radio buttons line up neatly.
The groupName will be referenced in the code. The labels will be manipulated to get
the values 0, 1, 2, 3, 4, 5, or 6 selected by the player. You also need to get a button to the
Stage. I used a standard button by clicking on Window/Common Libraries/ Buttons. I
needed to edit the button to change the text field to be what I wanted. Note that this
approach of using radio buttons plus another button means that the player needs to click
on two things. If the player just clicks the button, a message is displayed to make a
choice.
The code in actions layer, frame 2 (the frame labeled guessing) starts with import
statements to get the required built-in classes. The next statement declares (with a var
statement) a variable rg to be of type RadioButtonGroup and sets the value using a
command that gets the group with the indicated name. The next statement sets up the
event handler for the button to be the function getguess. The definition of
getguess determines the player's guess by a calculation on the label of the selected
radiobutton. The rest of the code generates the computer guess. It is an intelligent guess,
making use of the computer's number of coins. The code then checks if there was a
correct answer and displays the result in the res text field. After the definition of the
function, there is a stop(); statement. This keeps Flash from going back to the first
frame.
The code is:
import flash.events.Event;
import fl.events.ComponentEvent;
import fl.controls.RadioButtonGroup;
var rg:RadioButtonGroup =
RadioButtonGroup.getGroup("guesses");
guessbtn.addEventListener(MouseEvent.CLICK,getguess);
function getguess(ev) {
var pcguess:int;
var pcnotyetguessed:Boolean;
var choicelab:String;
if (rg.selection == null) {
res.text = "Please make a guess.";
} else {
choicelab = rg.selection.label;
playersguess = parseInt(choicelab.substr(0,1));
pcnotyetguessed = true;
while (pcnotyetguessed) {
pcguess = pcscoins +
Math.floor(Math.random()*4);
pcnotyetguessed = (pcguess == playersguess);
//if random pc guess is same as player's
guess, repeat
}
//now have a playersguess and a pcguess
//trace("pcguess is "+pcguess+" and sum is
"+sum);
if (playersguess == sum) {
res.text = "Player guessed correctly";
} else if (pcguess==sum) {
res.text = "PC guessed correctly";
} else {
res.text = "No one guessed. The answer was
"+sum;
}
}
}
stop();
If you want to see what is going on, remove the comment indicators: the //, from the line
with the trace. This shows the values of pcguess and sum.
Game with scoring
Keeping score is sometimes done by marking crosses on a board. To do this in Flash, I
chose to create in the Library a cross movie clip, set the Linkages to make it possible to
create instances dynamically. Create the cross by Insert/New Symbol Movie Clip. You
may want to use the Properties panel width and height to make the cross symmetrical (or
NOT), and the x and y settings to set the origin in the upper left corner (0,0). Then, right
click (or the MAC equivalent) on the Library panel and click on Linkages. Click on
Export for ActionScript and type in Cross in the Class field. Leave the Base class as is
and ignore the warning message. Since I do not need to add any extra functionality, the
default class definition of Cross will work.
Cross instances are added to the Stage by the code
var crossa:Cross = new Cross();
positioning the instance by setting x and y properties, and using the addChild method.
addChild(crossa);
This adds the newly created instance to what is termed the display list so we can see it.
The dynamically created crosses needed to be positioned on the board so that the new one
was not placed on top of the old one. I did this using variables and making sure not to
reset the value of the variables when returning to the first frame. I did this using the fact
that an int variable is set to a default value of 0.
Because the program goes back to the first frame, it was necessary to insert a pause to
give the player a chance to see the results. (See the memory game and tutorial). I used a
Timer object.
The added code for Frame 1 consists of additional variable definitions.:
var xplayer:int;
var xbarman:int;
//initialize horizontal positions for crosses, only set
once
if (xplayer==0) {
xplayer= -10;
xbarman= 310;
}
//use default of 0 for int values
var playerwins:int;
var barwins:int;
var crosswidth:int = 50;
var yp = 50;
The added code for Frame 2 is not enormous, but since it is in several places, I repeat all
the code. It starts with import statements, with one new one for flash.display.*. Next,
there are two statements concerning events. Following are function definitions for
getguess, endpause, and addcross.
import flash.events.Event;
import fl.events.ComponentEvent;
import fl.controls.RadioButtonGroup;
import flash.display.*;
var rg:RadioButtonGroup =
RadioButtonGroup.getGroup("guesses");
var pausetimer:Timer = new Timer(2000);
pausetimer.addEventListener(TimerEvent.TIMER,endpause);
guessbtn.addEventListener(MouseEvent.CLICK,getguess);
function getguess(ev) {
var pcguess:int;
var pcnotyetguessed:Boolean;
var choicelab:String;
if (rg.selection == null) {
res.text = "Please make a guess.";
} else {
choicelab = rg.selection.label;
playersguess = parseInt(choicelab.substr(0,1));
pcnotyetguessed = true;
while (pcnotyetguessed) {
pcguess = pcscoins +
Math.floor(Math.random()*4);
pcnotyetguessed = (pcguess == playersguess);
//if random pc guess is same as player's
guess, repeat
}
//now have a playersguess and a pcguess
//trace("pcguess is "+pcguess+" and sum is
"+sum);
if (playersguess == sum) {
res.text = "Player guessed correctly";
addcross("player");
playerwins++;
} else if (pcguess==sum) {
res.text = "Computer guessed correctly";
addcross("barman");
barwins++;
} else {
res.text = "No one guessed. The answer was
"+sum;
}
}
pausetimer.start();
}
function endpause(ev) {
pausetimer.stop();
if ((playerwins==3) || (barwins==3)) {
res.text = "GAME OVER ";
}
else {
gotoAndPlay(1);}
}
function addcross(who:String) {
var crossa:Cross = new Cross();
var xp:int;
if (who=="player") {
xplayer += crosswidth;
xp = xplayer;
}
else {
xbarman += crosswidth;
xp = xbarman;
}
crossa.x = xp;
crossa.y = yp;
addChild(crossa);
}
I have never played this game, so please send comments if the implementation is accurate
and also if it captures the spirit of the game.