Thunderjack! HTML5 Game Update: Completed the Logic for Blackjack Hands

Hello again!

We have more updates available for the HTML5 version of Thunderjack! using Phaser.

This time, we’re covering what happens when one or more players or the dealer gets a Blackjack.

As you may be aware, when a player gets a Blackjack on the opening hand, they are immediately paid, and do not play against the dealer. When the game first starts players who do have Blackjack will have their turns skipped, and the game starts with the first non-Blackjack player. If all players get a Blackjack, then the game ends.

If the dealer gets a Blackjack, then the game ends immediately. If any players also have a Blackjack, their result is a Push (the player gets their original bet back). All non-Blackjack players lose their bets.

Let’s get started on the logic for this might look like.

After all the cards are dealt, here is the basic rundown of the logic:

  1. Calculate the scores of all players and dealer
  2. Determine which hands, if any, have Blackjacks
  3. If the dealer has a blackjack:
    1. For each player that has a Blackjack, result is a push
    2. End game
  4. If the dealer does not have a Blackjack:
    1. For each player that has a Blackjack, is paid immediately, and does not play against the dealer
    2. Game starts with the first non-Blackjack player taking their turn.

We’ll tackle those one at a time.

1) Calculate the scores of all players and dealer

Every time one or more player’s or dealer’s hands change cards, we need to calculate how many points they have. As I hinted in this post, we have a Thunderjack.HandData class

Thunderjack.HandData = function(handId) {
  this.cardsData = [];
  this.handId = handId;
  this.score = 0;
  this.hasBlackjack = false;
};

We’re interested in the cardsData and score properties. The dealer will use this class to store data.

For the player, we need additional data that is exclusive on to the player. The player’s hand class looks like:

Thunderjack.PlayerHandData = function(handId) {
  Thunderjack.HandData.call(this, handId);
  this.isPush = false;
};

Because PlayerHandData inherits from HandData, it here we’re interested in the isPush property. The dealer can never push, which is why this property is nor defined in HandData.

We got into dealing the cards in this post. After the cards are dealt to a player, their cardsData property will contain the array of Thunderjack.CardData objects. The class looks like:

CardData
Thunderjack.CardData = function(cardValue, cardSuit, deckIndex) {
  this.value = cardValue;
  this.suit = cardSuit;
  this.deckIndex = deckIndex;
  this.id = this.value + "_" + this.suit + "_" + this.deckIndex;
};

We also talked Thunderjack.CardValues and the numeric values for each card:

CardPoints
Thunderjack.CardPoints = { };
Thunderjack.CardPoints[Thunderjack.CardValues.TWO] = 2;
Thunderjack.CardPoints[Thunderjack.CardValues.THREE] = 3;
Thunderjack.CardPoints[Thunderjack.CardValues.FOUR] = 4;
Thunderjack.CardPoints[Thunderjack.CardValues.FIVE] = 5;
Thunderjack.CardPoints[Thunderjack.CardValues.SIX] = 6;
Thunderjack.CardPoints[Thunderjack.CardValues.SEVEN] = 7;
Thunderjack.CardPoints[Thunderjack.CardValues.EIGHT] = 8;
Thunderjack.CardPoints[Thunderjack.CardValues.NINE] = 9;
Thunderjack.CardPoints[Thunderjack.CardValues.TEN] = 10;
Thunderjack.CardPoints[Thunderjack.CardValues.JACK] = 10;
Thunderjack.CardPoints[Thunderjack.CardValues.QUEEN] = 10;
Thunderjack.CardPoints[Thunderjack.CardValues.KING] = 10;
Thunderjack.CardPoints[Thunderjack.CardValues.ACE] = 1;

Now let’s wrote some code that figures out the players’ hand scores based on their cards. For the most part, it’s just adding up the values, but things are a little tricky with the ace, since it can be one or eleven.

CalcScore
Thunderjack.CalcScore.ACE_POINTS_REMAINING = 10;
Thunderjack.CalcScore.Eval = function (cardsData) {
  var points = 0;   var containsAnAce = false;
  for (var index = 0; index < cardsData.length; index++) {
    var cardData = cardsData[index];
    cardPoints = Thunderjack.CardPoints[cardData.value];
    if (cardData .value === Thunderjack.CardValues.ACE) {
      containsAnAce = true;
    }
    points += cardPoints;
  }

  if (containsAnAce) {
    var proposedValue = points + Thunderjack.CalcScore.ACE_POINTS_REMAINING;
    if (proposedValue <= Thunderjack.DesignData.BLACKJACK_POINTS) {
      points = proposedValue;
    }
  }
  return(points);
};


We’d call the Thunderjack.CalcScore.Eval function and send it the cardsData property of the hand we’re interested in.

We get the points of an individual card based on its value, then look it up in the Thunderjack.CardPoints object. For aces, we always add 1 point (for now), and we note that we’ve encountered at least one ace with the containsAnAce boolean.

If the hand contains an ace, we know that we can add the remaining 10 points of the high value of the ace to the points, as long as the results doesn’t exceed 21 (Thunderjack.DesignData.BLACKJACK_POINTS).

We eventually stored the returned result in the player’s hand. After all the cards have been dealt, we have these functions:

updateScores
function updateScores() {
  for each player in the game {
    player.handData.score = Thunderjack.CalcScore.Eval(player.handData.cardsData);
  }
  dealer.handData.score = Thunderjack.CalcScore.Eval(dealer.handData.cardsData);
}


Now the have the scores of all the players and dealer, we can evaluate their opening hands.

2) Determine which hands, if any, have Blackjacks. Here’s a quick pseudocode of the logic.

Here’s the break down:

if hasBlackjack(dealer) {
  handleDealerBlackjack();
  endRound();
} else {
  checkIfPlayersHaveBlackjacks();
  setFirstTurnPlayer();
}

Let’s start with determining if has a hand has a blackjack.

hasBlackjack
function hasBlackjack(player) {
  return (player.handData.score === Thunderjack.DesignData.BLACKJACK_POINTS);
}


As long as hasBlackjack is called after the scores have been update, the results will be accurate.

3) If the dealer has a blackjack:
3a) For each player that has a Blackjack, result is a push
3b) End game

We have a function specific to when the dealer has a Blackjack:

handleDealerBlackjack
function handleDealerBlackjack() {
  for each player in the game {
    if hasBlackjack(player) {
      player.handData.isPush = true;
    }
  }
  endRound();
}

Note that when the player has a Blackjack, we did not set the hasBlackjack property to true. Th is because the results is a push, even though the player got a Blackjack on their opening hand, they’re not being paid a Blackjack.

4 If the dealer does not have a Blackjack:
4a) For each player that has a Blackjack, is paid immediately, and does not play against the dealer
4b) Game starts with the first non-Blackjack player taking their turn

However, if the dealer does not have a Blackjack, we have code that handles below:

checkIfPlayersHaveBlackjacks
function checkIfPlayersHaveBlackjacks() {
  var bjHands = []
  for each player in the game {
    if hasBlackjack(player) {
      player.handData.hasBlackjack = true
      add player to bjHands array
    }
  }
  return bjHands
}
setFirstTurnPlayer
function setFirstTurnPlayer() {
  var turnPlayerIndex = getNextTurnPlayerIndex(0);
  if (turnPlayerIndex !== -1) {
    setTurnPlayer(turnPlayerIndex);
  } else {
    endRound();
  }
}

We’ve a some new function with setFirstTurnPlayer. There is a specific order in which the players take their turns. I’ve defined it as:

  1. Right player
  2. Middle player
  3. Left player
  4. Dealer

These are stored in an array called turnPlayerIds, and it will store the values we defined in Thunderjack.PlayerHandIds. These IDs were introduced in this article.

Thunderjack.PlayerHandIds.LOWER_RIGHT = "lowerRight";
Thunderjack.PlayerHandIds.LOWER_MIDDLE = "lowerMiddle";
Thunderjack.PlayerHandIds.LOWER_LEFT = "lowerLeft";
Thunderjack.PlayerHandIds.UPPER_RIGHT = "upperRight";
Thunderjack.PlayerHandIds.UPPER_MIDDLE = "upperMiddle";
Thunderjack.PlayerHandIds.UPPER_LEFT = "upperLeft";


So, assuming that all three player hands are active, turnPlayerIds would look like:

turnPlayerIds
turnPlayerIds = [
  Thunderjack.PlayerHandIds.LOWER_RIGHT,
  Thunderjack.PlayerHandIds.LOWER_MIDDLE,
  Thunderjack.PlayerHandIds.LOWER_LEFT,
  Thunderjack.PlayerHandIds.DEALER
];

(The “upper” hands are used for splitting, which we’ll go over in a later article.)

The first turn player will be the one who is eligible to play against the dealer. This is the player who did not get a Blackjack on their opening hand.

getNextTurnPlayerIndex
function getNextTurnPlayerIndex(startTurnPlayerIndex) {
  var index = startTurnPlayerIndex;
  while (index < turnPlayerIds.length) {
    var playerId = turnPlayerIds[index];
    var handData = playerHandsData[playerId];
    if (isPlayingVsDealer(handData)) {
      return(index);
    }
    index++;
  }

  return(-1);
}

The playerHandsData variable is an object that can store the player hands, indexed by their player IDs.

The isPlayingVsDealer function is what we can use to determine if a player will play vs the dealer. It looks like:

isPlayingVsDealer
function isPlayingVsDealer(handData) {
  return(!
    (playerHandData.hasBlackjack ||
    playerHandData.isPush));
};


If a player does not have a Blackjack or a push, they will play against the dealer. If there is no player to play against the dealer (getNextTurnPlayerIndex would return -1), then the game would end.

That’s it for this post. We covered quite a bit in these few steps, but most of the opening hand logic is done. In the next article, we’ll add my special feature to this game – winning a hand via Thunderjack! Stay tuned, and take care.

– C. out.

Thunderjack! HTML5 Game Update: Cheating? Yes But No

Hey guys. We’re into getting into some of the updates mentioned from my past post – mainly checking if an opening hand has a Blackjack, and eventually other specific combinations of cards in the hand. And there’s just one little problem… it can take all day to get the cards we need in order to test.

So, we’ll need a way to control the order in which cards are drawn. Otherwise, we may waiting a long time before we’re dealt the cards we want. So, we’ll have to cheat and pull a fast one here.

But before we get into that, let’s take a look at how the game sets up the cards and the deck.

Card Suits And Values

As you know, there are four suits and we have values from 2 to Ace. Let’s start with the suits first.

In Thunderjack!, we have a class called CardValues that acts like an enumeration, similar to what you might see in C# or Java. Except, we’ll be storing strings instead of integral values.

Thunderjack.CardSuits.HEARTS = "h";
Thunderjack.CardSuits.DIAMONDS = "d";
Thunderjack.CardSuits.CLUBS = "c";
Thunderjack.CardSuits.SPADES = "s";
Thunderjack.CardSuits.ALL = [
  Thunderjack.CardSuits.HEARTS,
  Thunderjack.CardSuits.DIAMONDS,
  Thunderjack.CardSuits.CLUBS,
  Thunderjack.CardSuits.SPADES
];

The ALL array is useful in iterating through all of the suits, which we’ll do later.

When storing the card values, you may think we’d use a number. However, we’ll going to use both string and number. The strings for suits and values will be used when creating unique IDs. We’ll get into these later, but for now, let’s have a look at the values.

We also have another ALL array for iterating through all of the values.

The CardPoints object stores the values, indexed by the string values defined above.

Thunderjack.CardValues.TWO = "2";
Thunderjack.CardValues.THREE = "3";
Thunderjack.CardValues.FOUR = "4";
Thunderjack.CardValues.FIVE = "5";
Thunderjack.CardValues.SIX = "6";
Thunderjack.CardValues.SEVEN = "7";
Thunderjack.CardValues.EIGHT = "8";
Thunderjack.CardValues.NINE = "9";
Thunderjack.CardValues.TEN = "10";
Thunderjack.CardValues.JACK = "j";
Thunderjack.CardValues.QUEEN = "q";
Thunderjack.CardValues.KING = "k";
Thunderjack.CardValues.ACE = "a";
Thunderjack.CardValues.ALL = [
  Thunderjack.CardValues.TWO,
  Thunderjack.CardValues.THREE,
  Thunderjack.CardValues.FOUR,
  Thunderjack.CardValues.FIVE,
  Thunderjack.CardValues.SIX,
  Thunderjack.CardValues.SEVEN,
  Thunderjack.CardValues.EIGHT,
  Thunderjack.CardValues.NINE,
  Thunderjack.CardValues.TEN,
  Thunderjack.CardValues.JACK,
  Thunderjack.CardValues.QUEEN,
  Thunderjack.CardValues.KING,
  Thunderjack.CardValues.ACE
];
Thunderjack.CardPoints = { };
Thunderjack.CardPoints[Thunderjack.CardValues.TWO] = 2;
Thunderjack.CardPoints[Thunderjack.CardValues.THREE] = 3;
Thunderjack.CardPoints[Thunderjack.CardValues.FOUR] = 4;
Thunderjack.CardPoints[Thunderjack.CardValues.FIVE] = 5;
Thunderjack.CardPoints[Thunderjack.CardValues.SIX] = 6;
Thunderjack.CardPoints[Thunderjack.CardValues.SEVEN] = 7;
Thunderjack.CardPoints[Thunderjack.CardValues.EIGHT] = 8;
Thunderjack.CardPoints[Thunderjack.CardValues.NINE] = 9;
Thunderjack.CardPoints[Thunderjack.CardValues.TEN] = 10;
Thunderjack.CardPoints[Thunderjack.CardValues.JACK] = 10;
Thunderjack.CardPoints[Thunderjack.CardValues.QUEEN] = 10;
Thunderjack.CardPoints[Thunderjack.CardValues.KING] = 10;
Thunderjack.CardPoints[Thunderjack.CardValues.ACE] = 1;

You may also notice that Ace only stores the value of 1 not 11. We’ll be using the 11 at another time, when we calculate how many points are in a player’s hand than contains an Ace. We won’t be using the CardPoints in this post, but we’ll need it soon.

Card Data Structure

Now that we have suites and values defined, we want a card data object that can store these. In Blackjack, more than one deck is commonly used, and Thunderjack! is no exception. This introduces the problem of having multiple cards with the same suit and value, and we want to be able to uniquely identify every card in each deck.

This is where the card ID that I mentioned earlier comes into play. We’ll be storing that in our data object, as well as the zero-based array index that identifies which deck the card represented by the card data object comes from.

This is what our card data object class looks like:

Thunderjack.CardData = function(s_cardValue, s_cardSuit, i_deckIndex) {
  this.value = s_cardValue;
  this.suit = s_cardSuit;
  this.deckIndex = i_deckIndex;
  this.id = this.value + "_" + this.suit + "_" + this.deckIndex;
};

As you can see, we’re forming our card ID as a string using the following format:
[card value] _ [card suit] _ [deck index]

For example, the seven of clubs from the third deck would look like this:
"7_c_2"

Deck Structure

Every card is represented by a card data object, and a deck is simply an array of 52 of these card data objects. We have a simple class for “dealing” and shuffling cards, as well as a few other utility functions.

Starting out, the deck data class looks like this:

//===========================================================================================
//"public"
//=========================================================================================== 

//===========================================================================================
//ctor
//===========================================================================================
Thunderjack.DeckData = function(i_numDecks) {
  //data: Thunderjack.CardData
  this._cardsData = [];
  this._init(i_numDecks);
};

//-------------------------------------------------------------------------------------------
//getLength
//-------------------------------------------------------------------------------------------
Thunderjack.DeckData.prototype.getLength = function() {
  return(this._cardsData.length);
};

//-------------------------------------------------------------------------------------------
//popCardData
//-------------------------------------------------------------------------------------------
Thunderjack.DeckData.prototype.popCardData = function() {
  return(this.getLength() > 0 ? this._cardsData.pop() : null);
};

//-------------------------------------------------------------------------------------------
//shuffle
//-------------------------------------------------------------------------------------------
Thunderjack.DeckData.prototype.shuffle = function() {
  Phaser.ArrayUtils.shuffle(this._cardsData);
};

//===========================================================================================
//"private"
//===========================================================================================

//-------------------------------------------------------------------------------------------
//_init
//-------------------------------------------------------------------------------------------
Thunderjack.DeckData.prototype._init = function(i_numDecks) {
  var i_decksCount;
  if (typeof i_numDecks === "number") {
    i_decksCount = i_numDecks;
  } else {
    return;
  }

  for (var i_deckIndex = 0; i_deckIndex < i_decksCount; i_deckIndex++) {
    for (var i_valueIndex = 0; i_valueIndex < Thunderjack.CardValues.ALL.length; i_valueIndex++) {
      var s_value = Thunderjack.CardValues.ALL[i_valueIndex];
      for (var i_suitIndex = 0; i_suitIndex < Thunderjack.CardSuits.ALL.length; i_suitIndex++) {
        var s_suit = Thunderjack.CardSuits.ALL[i_suitIndex];
        this._cardsData.push(new Thunderjack.CardData(s_value, s_suit, i_deckIndex));
      }
    }
  }
};

You can see in the _init method is where we create the CardData objects for each card in every deck. This is where we use the ALL arrays from CardSuits and CardValues.

Note that, instead of using those ALL properties, we could have also iterated through them using a for…in statement, but the arrays are useful in other parts of the game, which we won’t get into right now.

The method we’re interested in when dealing cards is DeckData.popCardData(). This will remove the last CardData object from the _cards array and return it to us. This is the basic structure of the DeckData class. There are other methods in this class as well, and they’ll be added as we need them.

You’ll also notice a shuffle method. Phaser already provides for us an ArrayUtils class, and so happens to have a shuffle method that randomizes the order of items in an array. We don’t have to write one ourselves. Remember, coders are lazy. (:

Get off yo ass and write some code!
Get off yo ass and write some code!
Dealing Cards to Each Player

With the deck and cards set up, we can now begin to deal cards to the players and dealer.
Some psuedocode looks like this:

function dealCardsToPlayers() {
  while (numberOfCardsDealtToEachPlayer < 2) {
    for each player in the game {
      dealCardToPlayer (player);
    }
    
    dealCardToPlayer (dealer);
    numberOfCardsDealtToEachPlayer++;
  }
}

When a card is dealt in dealCardToPlayer, it looks something like this:

function dealCardToPlayer (playerData) {
  var cardData = deckData.popCardData();
  playerData.cardsData.push(cardData);
}
Controlling the Order in Which Cards are Drawn (To Cheat!)

Now, if we’re trying to test out certain combinations of cards in a player’s hand, such as a Blackjack on the opening hand, we can be waiting a long ass time before we get what we’re looking for. This is where che~~~ ahem, controlling the order of the cards comes in.

The plan is like this:

  • Setup an array of card ID strings that will specify the order in which we want the cards to be drawn.
  • Shuffle the deck (if necessary)
  • After the cards have been shuffled, set the order of the cards in the deck according to the array of card Ids in step one.

Let’s setup each of these steps.

1). Setup an array of card ID strings that will specify the order in which we want the cards to be drawn.

We can set the array up that will hold the card IDs we want to use in the following:

debugCardIds = [
  "4_h_0",  //first card that will be dealt to the player
  "a_d_0",  //first card that will be dealt to the dealer
  "5_c_0",  //second card that will be dealt to the player
  "10_s_0"  // second card that will be dealt to the dealer
];

Say we have only one player and the dealer. From the card dealing snipped above, all players are dealt a card, then the dealer. Then this process continues until each player and the dealer has two cards.

2). Shuffle the deck (if necessary)

If we’re just starting the game, we’ll want to shuffle the deck. We can do that using the shuffle method of the DeckData class mentioned earlier.

deckData.shuffle();

3). After the cards have been shuffled, set the order of the cards in the deck according to the array of card Ids in step one.

function aceUpSleeve() {
  var s_cardId = _debugCardIds.shift();
  var i_swapIndex = _deckData.getLength();
  while (s_cardId) {
    _deckData.swap(s_cardId, --i_swapIndex);
    s_cardId = _debugCardIds.shift();
  }
}

What we’re doing here is using the shift method of JavaScript’s Array class to retrieve and remove the first card ID.

When dealing cards, remember that we retrieve and remove the last CardData object from the deck. So when setting up the deck in the order we want, we swap out the last card data object in the deck with debug card ID. Then, we work our way backwards, towards the beginning of the deck, until our debugCardsId array is empty.

The i_swapIndex variable represents the array index within the DeckData where we will place the CardData represented by our debug card ID. This is where a new method for DeckData, swap(), comes in:

Thunderjack.DeckData.prototype.swap = function(s_cardId, i_indexToSwapAt) {
  if (i_indexToSwapAt < 0 || i_indexToSwapAt >= this.getLength()) {
    return;
  }

  var i_indexOf = this.indexOfId(s_cardId);
  if (i_indexOf > -1) {
    var cardData = this._cardsData[i_indexToSwapAt];
    this._cardsData[i_indexToSwapAt] = this._cardsData[i_indexOf];
    this._cardsData[i_indexOf] = cardData;
  }
};

What this method does is first, locate the index within the _cardsData array of the CardData represented by our card debug ID, Then, it will swap the elements of the _cardsData array; the card data found at our requested swap index with the card data at the located index.

So now, our dealCardsToPlayers() method looks like this:

function dealCardsToPlayers() {
  //do this first – assume cards have been shuffled already in some other function
  aceUpSleeve();

  while (numberOfCardsDealtToEachPlayer < 2) {
    for each player in the game {
      dealCardToPlayer (player);
    }
    
    dealCardToPlayer (dealer);
    numberOfCardsDealtToEachPlayer++;
  }
}

Also, if we don’t want to control the order of dealing cards, we can set debugCardIds to an empty array.

The problem with this is, we have to keep editing the code when we want to control the order. Later on in development, I’ll build a user interface that allows us to manipulate the debug card Ids. Adding a debug/diagnostic interface like this is not something you’d put in a release version of your game, but they are invaluable when debugging, testing, and demoing your game.

Yes, they are a little bit of a detour, but it’s worth it. If you’re testing the game with someone else, they’ll be able to easily control the order of the deck without having to change the code. For my clients, they wouldn’t want to anyway – they just want something that’s easy for them to use without having to poke around in the code. That’s my job. 😉

Finally, you can watch this video of the *cough*cheat’n’*cough* in action. You may want to view the video at full-screen so you can see the edits I’m making in code. Also, after the opening cards are drawn each time, feel free to pause the video to check that the order of the cards drawn does indeed match with the _debugCardIds array (they do):

So that’s it for now. This was a long one, and thanks for reading all the way to the end. I can’t wait until this game is finished for you all to play!

– C. out.

Thunderjack! Playing Against The Dealer

Hey there, and welcome back for another update on the HTML5 Phaser version of Thunderjack!.

The project is starting to get interesting, because most of the UI is done, and I have begun working on the game mechanics and logic.

Updates include:

  1. Hit and Stand functions are complete.
  2. The dealer now plays (dealer AI) if there are any eligible players remaining.
  3. At the end of the round, winners are determined by comparing hands.
  4. A new round can now be played.

Let’s go over each of these in a little more detail.

1. Hit and Stand functions are complete

When taking a hit, the bust functionality is now complete. If a player’s score exceeds 21, the player will bust, and the Bust indicator will appear. The game then moves to the next available player.

Likewise, the player can stand. If they do so, the game then moves to the next available player.

A few notes on available players.

Thunderjack! Will allow you to place bets on one to three players. Since splitting is supported in this game, it is possible for you to split the hands to play a total of six hands in a round.

I assigned a “player ID” to each of the six players. This ID is a string that is used when referencing any of the player data, such as:

  • cards in hand
  • score
  • status (bust, blackjack, Thunderjack, etc.)
  • bet amount

The player ID is also used to reference the graphical UI for each player. Things like:

  • card graphics;
  • textfield for the score;
  • textfield for the bet value;
  • chips that represent the bet value; and
  • result label (won, bust, blackjack, etc.)

The player IDs are setup in code like this:

PlayerHandIds.LOWER_RIGHT = "lowerRight";
PlayerHandIds.LOWER_MIDDLE = "lowerMiddle";
PlayerHandIds.LOWER_LEFT = "lowerLeft";
PlayerHandIds.UPPER_RIGHT = "upperRight";
PlayerHandIds.UPPER_MIDDLE = "upperMiddle";
PlayerHandIds.UPPER_LEFT = "upperLeft";

When starting a round, you can play on any of the three “lower” hands. The “upper” hands are used for splitting, which will be implemented later.

There are also some additional IDs:

PlayerHandIds.DEALER = "dealer";
PlayerHandIds.DECK = "deck";
PlayerHandIds.DISCARD_DECK = "discardDeck";

The ID, PlayerHandIds.DEALER, is very similar to the six players, except that it does not use betting information, and it cannot split or double-down.

The ID, PlayerHandIds.DECK, is used when moving cards back into the deck (for reshuffling)

The ID, PlayerHandIds.DISCARD_DECK, is used at the end of each round when all players place all the cards in the hand into the discarded deck.

2. The dealer now plays (dealer AI) if there are any eligible players remaining

The logic for the dealer is simple. If if has less than seventeen points, it will take a Hit. Otherwise, it will stay. Also, the dealer does not double-down or surrender.

The dealer will play its hand only if there are any eligible players remaining to play against it.

An eligible player is a player who:

  • did not bust
  • did not get a blackjack, Thunderjack, or blitz
  • did not surrender

If there are no eligible players, the round ends, and the dealer does not play.

3. At the end of the round, eligible players now play against the dealer

When all players and the dealer have completed their turns, the hands of eligible players are compared against the dealer’s to determine winners.

4. A new round can now be played

After the round has ended, you can play a new round with the same bets, or you can set new bets on your hands. When you start a new game, all cards in the players’ and dealer’s hands are moved to the discard deck, then players are dealt new hands from the deck.

Have a look at this video to see the current progress:

Following Updates

As you can see, the game is coming along nicely. You may have noticed a few other details I didn’t mention, such as showing how much player’s won, or the credits in the upper-left corner of the screen are now being deducted when starting a game. Or, maybe you noticed that the credits didn’t increase when players win!

Ha! No, I’m not trying to put the shit on anybody; I just haven’t gotten to that part yet.

But let me go ahead and state some of the updates to come in the game:

  • Credits increase when players win.
  • Finish showing all the result indicators. Bust and Win show, but the others, like Blackjack or Push, show. Which brings me to the next to-do items.
  • Complete logic for Blackjack for player. If a player gets a Blackjack, that player’s turn immediately ends, he/she receives an immediate payout, and it becomes the next eligible player’s turn. A player who gets a blackjack becomes ineligible to play against the dealer.
  • Complete logic Blackjack for dealer. If the dealer gets a Blackjack, the game immediately ends and and player hands are compared against the dealer. Any player who has a blackjack results in a push. Players who get a Thunderjack! Will actually beat the dealer (this will be implement a bit later on). Otherwise, all other players don’t win the round.
  • If a player’s hand results in a push, they get their original bet back.
  • As cards are added to or removed from the deck, visually update it’s deck accordingly.
  • As cards are added to or removed from the discard pile, visually update it’s deck accordingly.
  • If too many cards have been used from the deck, before dealing the next wave of cards to the player and dealer, all discarded cards will be returned to the deck, the deck will be shuffled.

If you like where this is going, please leave me a comment saying what you like. Of course, if you don’t like it, that’s cool, too. (:

If you want be to build a Blackjack-style type of game for you (or a breakout style game like this or that), then please contact me here, contact me directly at cartrell@gameplaycoder.com, or look me up on LinkedIn.

That’s all I have for you for now. Thanks, and stay tuned for the next update.

– C. out.

Thunderjack! HTML5 Game Update: Card Dealing

Hey guys.

Welcome back to Gameplay Coder. Quite a bit of progress has been made on the HTML5 version of Thunderjack! using Phaser and the Phaser Editor. I’m getting the hang of basic usage of the editor. And it’s great to have a visual editor at your disposal – so you don’t have to place sprites using hard-coded x/y coordinates via trial and error, or reply on some external graphics tool then have to copy/paste those coordinates.

Updates to this game include:

  1. Being able to place bets.
  2. Dealing the cards to the players and dealer.
  3. Updating points for the players.

Hit functionality is currently in the works, as is determining when a player or dealer has a blackjack, and when a player has a Thunderjack.

Use of Fonts

One issue I encountered is with using fonts. In the browser, they don’t appear exactly as the do in the editor. Some features such as stroke, aren’t rendered. So I’ll likely end up using Phaser bitmap fonts instead of fonts, which, on my machine, is a small set of Windows fonts that the editor has access to. Furthermore, there is no guarantee that the fonts used in the project will be installed on the machine of someone playing the game.

There is an online Flash tool (at the time of this post), called Littera. This can be used to create bitmap fonts from fonts installed on your machine. What’s also cool about it is, Phaser supports the format, as shown in this example.

Prototypal Inheritance

While I’m no stranger to OOP (object-oriented programming) and classical inheritance in languages like ActionScript 3, C# or Java, I’m fairly new as to prototypal inheritance in JavaScript, so I’m giving it a try in this project. Hell yeah! 💪🏾

I’m using prototypal inheritance with the data that stores the player hands and the dealer hand. There is a ‘base class’ called HandData, whose function constructor looks like this:

HandData class
HandData = function(s_handId) {
  this.cards = [];
  this.handId = s_handId;
  this.score = 0;
  this.hasBlackjack = false;
  this.isBust = false;
};

This is basic data that both types of hands, player and dealer, will contain.

However, player hands will need to store additional data, such as the bet amount, and can perform other moves such as split, double, and surrender. Players can also win via Blitz (6-card Charlie in this game). The dealer does not use any of these functions, and thus doesn’t need access to them.

The player hand data, PlayerHandData, will inherit from the HandData, and looks like this:

PlayerHandData class
PlayerHandData = function(s_handId) {
  HandData.call(this, s_handId);
  this.betValue = 0;
  this.hasThunderjack = false;
  this.isPush = false;
  this.hasBlitz = false;
  this.hasDoubled = false;
  this.hasSurrendered = false;
};

That call() function is like calling the constructor of the parent class. In this case, it sends the parameters that were sent when it was created onto its parent constructor. Also, the this keyword is supplied first, so that the context in which the parent constructor function is being called is set to the inheriting function constructor.

However, PlayerHandData still needs to have its constructor inherit the methods of the parent prototype. This creates a new object based on the parent prototype:

PlayerHandData.prototype = Object.create(HandData.prototype);

And finally, the constructor of our new PlayerHandData prototype needs to point to PlayerHandData instead of HandData. That can be fixed with this line:
PlayerHandData.prototype.constructor = PlayerHandData;

Now when we create data for each the dealer hand, we can write:
var dealerHand = new HandData(s_dealerId);

And for each of the six player hands, we can write something like:
var somePlayerHand = new PlayerHandData(s_playerId);

The player hand will have all the properties of the dealer hand, plus the extras that are required to support the additional game play available to the players.

So when inheriting one “class” from another (I put “class” in quotes because, JavaScript doesn’t have classes. They can be simulated using prototypes.), it’s basically three steps:

1). Within the inheriting function constructor, call the parent constructor function using the call(). Be sure to set this as the first parameter, succeeded by any function constructor parameters.
2). Create a copy of the parent function’s prototype, and assign it to the inheriting constructor function’s prototype.
3). Assign the constructor of the inheriting prototype to the inheriting constructor function itself.

This can be a little confusing, but typing this out can help reinforce learning (though writing it out is better, studies have shown, but I digress (:

But doing is the best way to learn, in my opinion, of course. So, I’ll definitely take more opportunities to apply this so it becomes easier.

Whew!

Well!… Lemme get a sippa water…
* Ahhhhh! *

Moving on, here is a short video of what I have so far. It’s what was mentioned in the updates mentioned near the start of this article.

It’s not much, but under the hood, a lot has been accomplished, and with most of the lower-level code now out of the way, I can start getting into the fun stuff!

Thanks for stick with me guys, and stay tuned for more.

– C. out.

Laser Stryker Deluxe

Hey guys.

Let me introduce you to a new game I’m working on (besides the Android and HTML5 versions of Thunderjack!).

This is the next project from the Unity course over on Udemy called Complete C# Unity Developer 2D – Learn to Code Making Games. It’s a space shooter game that teaches you about moving objects in such a way that is independent of frame rate, coroutines, moving objects along a predefined path, using for-each loops, and backgrounds that scroll indefinitely.

I decided to call my version of this game “Laser Stryker Deluxe” as it’s a sort of spin-off to Laser Strykyer, a Flash game I made a while back (which pays homage to a game on the ColecoVision called Beamrider).

LDeluxe will feature most of the graphics from the original Laser Stryker. Because the game in the Unity course resembles the mechanics of a classic vertical shooter, Deluxe will use a similar setup. It will also feature power-ups, such as additional weapons, speed, armor, and maybe weapon charging – many of the features that are found in games of this genre.

I’m learning a lot in this 2D Unity course, and I’m super-excited to bring this game to life!

Although I’ve completed this section of the course, I want to expand on LDeluxe before moving on the the next section.

Here’s a quick look at the very early stages of development process so far. I can’t wait until I’m finished so I can show this bad boy off.

– C. out.

Brickout: Polish Update

Hey there.

Polish can easily be overlooked when developing a game. It’s that last 10 percent or so where you smooth out the rough edges, focus on the intricacies of mechanics or functionality, and sharpen up audio, visuals and feedback. Polish is what can turn a bad game into a good game, and a good one into a great one, all else being equal.

No, not that kind of polish.

A bit of progress has been made to add polish to Brickout. Let’s demonstrate what’s done so far.

Added particle effects to broken bricks.

Getting into Phaser’s particle system wasn’t too difficult. I created a simple graphic that represents a broken piece of the brick, and used that as the particle. Every brick has its particles that match its own color.

Extra Impact to Bomb Explosions

When a bomb explodes, it now produces a screen flash and tremor.

This one was a lot of fun to add. The flash made use of Phaser’s graphic primitive functionality. In this case, I used a colored rectangle that fills the entire screen.

The tremor was super-easy. Interestingly enough, there is a “shake” method on Phaser’s Camera object that you can call, and specify the intensity and duration of the tremor. In previous games I’ve made for clients, I’ve always had to do this manually, and I was expecting to do that here. Thankfully (or unfortunately, if you’re a crazy coder (:  ), that’s a task I’m relieved of for this game. (:

There is also a “shattering” sound that is played if the bomb happens to clear any bricks within its blast area.

Saver Blocks Gradually Appear Instead of All at Once

When the saver bridge is forming itself, it now does so once brick at a time. So, you’re not out of the woods yet, and you can still lose a ball while the bridge is forming!

Also added particles to broken saver bricks as well.

Adding Labels to Identify the Item Collected

When you collect gems, an animated label will briefly appear. For some items, such as the bomb or saver bridge, this is not necessary.

Alright! Let’s see this shit in action!  😀

Now, more work to do!

– C. out.

Polishing Up Brickout

Hey what’s up!

The gameplay is pretty much done. Now it’s time to start polishing up the mechanics and effects. The next steps are:

– Adding particles to broken bricks (This means learning how to use Phaser’s particle system. Cool!)
– Adding a screen flash to bomb explosions. In addition to the a screen tremor, let’s add some impact to those bombs. (User of Phaser’s Graphics – draw primitives, specifically, the rectangle)
– Saver blocks appear gradually instead of all at once (Use of Phaser’s Timer system)
– Adding labels that say what power up item was just collected
– Adding particles to broken saver blocks
– When bricks are cleared with Color Match or Color Blast:
a) gradually destroy the blocks instead of all at once
b) add a screen tremor effect
c) add sound effect (different from the normal brick breaking)
– When serving the ball into play, give the player more control over where it goes. I plan on “sliding” the ball across the paddle, thus giving the player the opportunity to “aim” the ball. Check out this video:

– Adding game over when all lives (balls) are lost.

That should do it. After this, I’ll add a few more levels, and play around with balancing the items (rates of occurrence, duration and intensity of effects, and such [for game balance/feedback purposes]), do a bit more play-testing, then that should be it.

Almost there guys! Thanks for staying tuned, and comment if you’ve any questions on anything.

And for the record, yes, the game will be freely available to play on the site, as well as the source code being released.

Take care,

– C. out.

Thunderjack!

Hey guys,

As I mentioned earlier, I recently completed the Android Basics Nanodegree program offered by Udacity. During the course, I decided to create a side project, completely independent of the course material. The project not only uses some of the concepts from the course, but also expands on concepts beyond the scope of the course. This is where the real fun is, because these are uncharted waters that present unique challenges.

This project I’m working on – besides Brickout, which is an HTML5 game using Phaser – is a called Thunderjack. It’s Blackjack, but with my own spins on it, mostly just some over-the-top theatrics, and playing around with some of the rules. (:

The awesome Thunderjack!

I’ve been working on this for a few months now, reinforcing my knowledge of Android Studio, Java, and Android development. One caveat I’ve found is, Android Studio is not the most ideal IDE for building an Android game, at least not one that fits well into your typical layout schemes such as Linear, Relative, or Constraint. For the record though, I went with the Constraint layout, mainly because of it’s guides functionality, which can use percentages of the screen, which makes designing a responsive app much easier.

One problem I ran into was trying to fit all the blackjack elements on the display. They include:

1). Three lower player hands
2). Three upper player hands. Each hand can split, so you can play up to six hands at a time
3). Positioning the cards so they cascade atop each other, but still able to see what the cards are
3). Betting chips
4). Dealer’s hand
5). Results (bust, win, etc.)
6). Text for displaying credits, and score of each hand
7). Action buttons (hit, stand, etc)
8). Turn indicator arrows (whose turn it currently is)

As you see imagine, the underlying constraint layout is quite massive! And it’s Landscape orientation only; ain-no way in the hell all this was gonna fit on a Portrait orientation, and still be easy to see, especially on phones.

A peculiar issue I faced was a performance issue that took me a while to track down. It was due to rendering of TextView objects inside the TextView, probably because of all the re-calculating that goes on under the hood. This presented a big problem, because it meant that I would have to scrap the entire Constraint layout! But the constraints allow me to establish that responsiveness across various device sizes! Sigh… shit. Time to get creative…

I didn’t scrap the Constraint layout. Not exactly. What I did was:
1). Start again with a blank constraint layout.
2). Examined each visual element (text, button, image, etc), and cloned it
3). Placed the clone element on the blank layout in the same position of the original element
4). Deleted the constraint layout
5). The blank layout becomes the official layout that is shown.

While this created a lot more work, it also allowed me to re-created the layout with all the responsiveness, but without all performance hit of the constraints. I believe I can get away with this, because of its static nature. Other than the cards, which all move to predetermined positions on the layout, there aren’t any dynamic elements on here. In other words, nothing needs resizing or repositioning.

Another challenge is use of sound effects.

The Android Basics course does talk about use of the MediaPlayer.

As you know, games often play multiple sounds at once, and it seems that MediaPlayer can only play one sound at a time.

So, I found a class called SoundPool class that allows you to load up several sounds, and is designed for smaller sounds. This seemed to be exactly what I was looking for, until I found that it has no notification callback support for when a sound has finished playing, which is also a functionality I need. MediaPlayer however, does have this.

So, the approach I’m taking is a hybrid one. Basically, I’m using SoundPool for all the sounds I can play and forget about, while the MediaPlayer can play those sounds where I need to be notified when they complete, so I can take appropriate actions.

However, SoundPool doesn’t come without its caveats either. You need to specify a max number of sounds it can play at once by loading them into the SoundPool, and if you need to play a sound that isn’t loaded, one of the other sounds must get discarded. I’m currently working on a way around this, because my first implementation introduces a bit of lag when loading some sounds. But, I’m confident I’ll have an unorthodox solution for this. 😉

That’s it for now. I’ll keep you guys updated on the progress of this one. I should have it done and into the Google Play Store later this year.

Thanks!

– C. out.

Sound Effects

What’s up, guys.

Brickout now has the sound effects added! I also snuck some of my jazzy musical skills into many of the sound effects.

A short video with the sounds is below. Things got a bit crazy around the 1:00 mark in the video! I think I’ma keep this aspect of the game design, though. Then it got really boring, trying to hit that LAST brick… dammit!  >:D

But, I’m happy that with 41 sound effects added, most of them are done now. (:

Playing sounds using Phaser and its SoundManager class was easier than I thought! I still need to implement callback notifications when a sound has finished playing, because I will need that functionality a little later.

After watching the video, share your opinions in the comments below. I’m curious to know. Thanks!

– C. out.

Color Blast Item Added

Hey.

A new item has been added to Brickout. This item is called the “Color Blast”, and to get it you need to collect the purple gem.

What this item does it it will remove the bricks with the most common color. For example, in the demo video below, when the Color Blast gem is collected, it removes all the green bricks, because there are more green bricks than any other color of brick on the board.

This item was fairly easy to implement using the current code engine I’ve already built.

More items will be added soon, so keep watching!

– C. out.