Sunday, December 15, 2019

Video Poker part 1

This is the first half of Chapter 8 of my "Creating HTML5 Games Using AnimateCC" eBook that I was releasing on my Blazing Games Development Blog but am now going to be posting here as I am now just going to have a single blog. For earlier posts in the series, visit the other blog. Unlike earlier posts, I want longer form posts so will be posting the first half of the chapter this month and next month will be posting the second half (instead of having 8 sections spread out).

Chapter 8 - Video Poker (part 1)

Game Layout

Video Poker is a simulation of a video-based gambling game found at many casinos. As such, it makes sense to have a background that reflects this fact by making the game display look like a cabinet with a monitor in it. This is done in two layers. The “Screenback” layer holds the screen and the “Console” layer holds the console (outer part of the machine). The figures below shows the “Screenback” layer and the “Console” layer.


The screen background layer (“Screenback”) is a radial gradient filled rectangle using shades of green to give the impression of older CRT displays. Perhaps this aesthetic reflects my age as pretty much any casino that you go into today will have more modern LCD or better displays. I like the older look, but that could be a reflection of your age. Choose the aesthetic that you, or better yet your target audience, would prefer.



The games are housed in a cabinet which I originally called a console thinking of the term for video game systems not the proper term for the physical machines but I only realized the mistake well after the game was finished so am leaving the incorrect terminology in the code. If in the future I was going to alter the code, a refactoring step to properly rename the layer may be worth the effort.

In order to actually play the game, we are going to need a few more layers. The layers used in the movie are “Code,” “Info,” “Bet,” “Console,” “FRCard,” “RCard,” “CCard,” “LCard,” “FLCard,” and “Screenback.” The combination of these layers results in our final layout as can be seen in figure below.



The Code layer is where we place our code and labels. The “Console” and “Screenback” layers were described above. The “FRCard” layer holds the card on the far right. The “RCard” layer holds the card on the right. And so on. We simply place a card object on each of the layers. The card instances are named, “FLCard\_movie,” “LCard\_movie,” “CCard\_movie,” “Rcard\_movie,” and “FRCard\_movie.” To make sure the cards are aligned vertically and spaced evenly, you can use the align submenu under the modify menu. To use this, select the objects you want to align by clicking on them while the shift key is down and then choose the alignment option of your choice.

Now, the info layer is going to contains a line of text that gives players instructions and results. Quite simply, we create this layer by creating a dynamic text object using a red 50 point “\_sans” font and naming the instance “results\_txt.” We also create dynamic text objects for the bet, last win and current balance. These will be created using a green 20 point “\_sans” font. The instances will be named “bet\_text,” “win\_txt,” and “balance\_txt.” Later on we will be adding Draw movies to this layer.

The bet layer is mostly blank. It only appears when the bet buttons are active. The rest of the time the player will only see the non-functioning buttons that are part of the console image.

We want to make sure that we import our deck class. This is done by going to the actions panel. Within that panel you can specify which scripts you wish to add to the project. Selecting the script option lets you add scripts to the game. The order of the scripts is important as it determines the loading order of the scripts so if one script depends on another script you may need to make sure the depended-on script is loaded first.

This leads to the problem of where to place the code. As with the NIM game, we are opting to write the code in the provided script section which has the advantage of keeping all the game logic within the .fla file but as we are loading an external file for the card library, some of you may be wondering if it would be possible to keep the code outside of flash. The answer to this is yes, and it is something that we will be doing with some of the other projects in this book.

Betting


Video poker, and poker in general for that matter, is a casino game. This means that betting is an important aspect of the game. In a casino, the video poker games I have seen are based around a unit of currency. That unit, be it nickles, quarters, or dollars is the amount of a bet. Most machines allow for more than one unit be bet at a time. I have decided that my virtual machine will allow for 1 to 5 units to be used.

As you seen last chapter, the background console already has buttons drawn. These are not usable. What we are going to do is create a button class that looks like the console button but lit up. This is a common casino convention to let the player know what options are currently selectable. This lit up button will be placed over top the console image so to the user it will appear as if the console has lit up the button. Figure \ref{fig:betbuttons} shows the four frames that make up one of the buttons.



Placing the buttons over their corresponding console button is simply a matter of zooming in the image and using the cursor keys to finely position the buttons. The button instance names are labeled “bet1\_btn,” “bet2\_btn,” “bet3\_btn,” “bet4\_btn” and “bet5\_btn.” Now we are ready to start adding code.

Within the global script player we start by creating the constructor function for our videoPokerGame class which will have additional functions added to it This code simply sets the players cumulative winnings to 0, the amount of the last win to 0, and creates a deck of cards using the card library that was created in the previous chapter.

// Global Scripts
videoPokerGame = new VideoPokerGame();
function VideoPokerGame()
{
console.log("Created Video Poker Game Instance");
this.cash = 0;
this.lastWin = 0;
this.myDeck = new spelchan.Deck();
}

One issue that I came across when first experimenting with Adobe Animate CC was when trying to access the stage variable so I could access variables in the movie clip that is currently active.  There may be a better way of doing this, but my quick solution is to simply pass the MovieClip instance to the initGame function whenever a game is being initialized.

The initGame function sets up base game variables, resets the current instructional message for the game, then sets up the cards and the listeners for the cards. The card values are stored in a hand array registering the appropriate MovieClip representation of the card. Each card has a draw message tied to it as well to let the player know which cards are going to be drawn. These are stored in the drawMovies array. .

VideoPokerGame.prototype.initGame = function(vpMovie) 
{
this.vpMovie = vpMovie;
this.selecting = false;
this.bet = 0;
this.message = "?";
this.hand = new Array(
new spelchan.Card(vpMovie.FLCard_movie),
new spelchan.Card(vpMovie.LCard_movie), 
new spelchan.Card(vpMovie.CCard_movie), 
new spelchan.Card(vpMovie.RCard_movie), 
new spelchan.Card(vpMovie.FRCard_movie)
);
this.drawMovie = new Array(vpMovie.draw1_movie, vpMovie.draw2_movie, vpMovie.draw3_movie,
vpMovie.draw4_movie, vpMovie.draw5_movie);
for (var cntr = 0; cntr < 5; ++cntr)
{
this.drawMovie[cntr].visible = false;
this.hand[cntr].cardMovie.addEventListener("click", this.handleCardClick.bind(this, cntr));
}
}

The initialization sets the message by calling an updateText function which not only displays the indicated message but also updates the betting, player cash balance, and the last amount that the player has won. This is done by simply setting the text value of the appropriate text objects that were used to make the text.

VideoPokerGame.prototype.updateText = function()
{
this.vpMovie.results_text.text = this.message;
this.vpMovie.bet_text.text = "Betting: " + this.bet;
this.vpMovie.balance_text.text = "Balance: " + this.cash;
this.vpMovie.win_text.text = "Last Win: " + this.lastWin;
}

The card MovieClips have an event listener attached to them. This simply sees if we are in a part of the game where you can select cards for the card draw and if so toggles whether that card should be drawn.

VideoPokerGame.prototype.handleCardClick = function(n, event) {
if (this.selecting != true)
return;
console.log("Should be toggling draw for slot " + n);
this.drawMovie[n].visible = !this.drawMovie[n].visible;
}

The code to call the game initialization needs to be added to the second frame of the games’ timeline on the Code layer. The easiest way of doing this is to right-click on the frame in the timeline and add a blank keyframe if one does not exist then right-click on that blank keyframe and select actions which should open the code editor for that frame. Once you have code on a frame, simply selecting it from the list of code segments on the left of the action window will let you quickly select the frame for which you wish to edit code. The code on this frame is simply a call to the global videoPokerGame game calling the initGame function that we created above.

videoPokerGame.initGame(this);

The third frame of the code layer we label “BetWait.” This will be the location the movie moves to whenever the player is required to make another bet. To handle the betting the frame calls a method in the global VideoPokerGame instance. The code to place on frame 4 is a simple function call.

videoPokerGame.startWaitForBets();


This function doesn’t exist in our VideoPokerGame class so we need to create it. The first thing the function needs to do is set up the message to a "Please make a bet..." message. We then make sure that none of the draw labels are visible by loping through them and turning off their visibility. The movie playback is stopped so that this frame will be shown until a bet has been made. This is where things get rather interesting. JavaScript handles scope a bit different from other object-oriented languages and as a result a call to a method within a class will be called with the wrong value for the this variable. To correct for this, we need to bind the correct reference to use. This information needs to be saved so that when we remove the event listener we are removing the proper listener.

The fact that we are binding things to the event call actually makes things a bit easier than they were In ActionScript as you are then able to add additional parameters to the function call so that the same handler can more easily handle multiple events. In our case we are going to have a handleBet event handler which will take the amount of the bet as it’s parameter.

Once the bindings are created, we simply add a “click” event listener to each of the five buttons using the boundedBet tied to that button.

VideoPokerGame.prototype.startWaitForBets = function(){
this.message = "Please make a bet...";
this.updateText();
for (var cntr = 0; cntr < 5; ++cntr)
{
this.drawMovie[cntr].visible = false;
}
this.vpMovie.stop();
// create bindings for bets
this.boundBet1 = this.handleBet.bind(this, 1);
this.boundBet2 = this.handleBet.bind(this, 2);
this.boundBet3 = this.handleBet.bind(this, 3);
this.boundBet4 = this.handleBet.bind(this, 4);
this.boundBet5 = this.handleBet.bind(this, 5);
// listen for bets
this.vpMovie.bet1_btn.addEventListener("click", this.boundBet1);
this.vpMovie.bet2_btn.addEventListener("click", this.boundBet2); 
this.vpMovie.bet3_btn.addEventListener("click", this.boundBet3);
this.vpMovie.bet4_btn.addEventListener("click", this.boundBet4);
this.vpMovie.bet5_btn.addEventListener("click", this.boundBet5);
}

When a bet has been made, the handleBet function get called with the amount of the bet. It simply records the amount of the bet, removes the event listeners from the bet buttons, clears the message, adjusts the player’s cash balance, then starts the game timeline which will advance into the ClearCards section of the game movie.

VideoPokerGame.prototype.handleBet = function(bet, event) {
this.bet = bet;
console.log("Made a bet of " + this.bet);
this.vpMovie.bet1_btn.removeEventListener("click", this.boundBet1);
this.vpMovie.bet2_btn.removeEventListener("click", this.boundBet2); 
this.vpMovie.bet3_btn.removeEventListener("click", this.boundBet3);
this.vpMovie.bet4_btn.removeEventListener("click", this.boundBet4);
this.vpMovie.bet5_btn.removeEventListener("click", this.boundBet5);
this.message = " ";
this.cash -= bet;
this.updateText();
this.vpMovie.play();
}


Revealing the Hand


The revealing of the initial drawing of cards is done in three phases. The first phase the cards are removed from the game play field. This is simply a matter of moving the cards, each card separated by a few frames, from it's current position to a position along the top of the screen while changing the size of the card to 20\%. This is done in the movie section labeled “ClearCards.” I placed the moves in frames 5, 8, 11, 14, and 17. A shuffle sound is added to the “Sound” layer to play a shuffling sound whle the cards are being removed. The figure below shows the timeline for the dealing phase of the game.



On frame 20 of the code layer we create a keyframe labeled “Deal.” In frame 20 we also call our video poker game instance to deal the cards. We also need to add a draw sound on frame 20, 25, 30, 35, and 40. The code on frame 20 is simply a call to our deal method.

videoPokerGame.deal();

The code for handling the dealing is in the global script.  The deal function simply makes use of the card library we created in the previous chapter to shuffle the deck then grabs the first five cards off the deck. The card is set to show the face just in case the face wasn’t showing.

VideoPokerGame.prototype.deal = function()
{
var cntr;
this.myDeck.shuffle();
for (cntr = 0; cntr < 5; ++cntr)
{
this.hand[cntr].setCard(this.myDeck.draw());
this.hand[cntr].showFace();
}
}

Finally we animate the cards going from their top position to their proper final locations. What I do is stagger the starting frame of the reveal animation by five frames, yet have the reveal animation take 10 frames. In other words, we have starting frames of 20, 25, 30, 35 and 40. Each card moves from the hidden spot at the top to it’s proper position and at the same time returns to it’s normal size. This is a simple motion tween for all five of the cards.

Next half of the chapter will be released next month where we implement the selection and scoring of hands.