Overlapping Sprites with Phaser3

In this tutorial we are going to overlap two sprite sheets to make the visuals for a deck of cards. Then we will shuffle the deck and use a tween timeline to deal out 5 cards.

First let's set up a basic Phaser3 project.

<!doctype html> 
<html lang="en"> 

<head> 
    <meta charset="UTF-8" />
    <title>Deck of Cards</title>

    <script src="phaser.min.js"></script>
	
    <style type="text/css">

        body {
            margin: 0;
        }

    </style>
</head>

<body>

<script>

var config = {
    width: 800,
    height: 600,
	backgroundColor: '#dddddd',
    type: Phaser.AUTO,
    scene: {
        preload: preload,
        create: create
    }
};

var game = new Phaser.Game(config);

function preload ()
{
      

}

function create ()
{


}


</script>

</body>
</html>

Here are the two sprite sheets I created.



One sprite sheet for the card suits and one for the card value or number.

By overlapping the sprite sheets, I can make a complete deck of cards.

Lets add them to our preload function.

function preload ()
{
       this.load.spritesheet('suit', 'assets/suits.png', { frameWidth: 60, frameHeight: 90 });
       this.load.spritesheet('number', 'assets/numbers.png', { frameWidth: 60, frameHeight: 75 });

}

Next, we need a variable to hold the deck of cards, one for the five cards we will deal out, and one extra to represent the stacked deck.
Add them just above the game variable.

var deck;
var playerhand;
var deckSprite;

var game = new Phaser.Game(config);

Then make a deck of cards inside the create function, shuffle the deck, and give the first five cards to the playerhand variable.

function create ()
{

  //These are arrays
  deck = [];
  playerhand = [];

  //create the deck of 52 cards
  for(let j = 0; j < 4; j++) {
    let suit = j;
    for(let i = 0; i < 13; i++) {
        let number = i;
        deck.push(new Card(number, i+2, suit));
    }
  }
  
  //shuffle the deck
  deck = Phaser.Utils.Array.Shuffle(deck);
  
  deckSprite = this.add.sprite(400, -100, "suit", 4).setScale(2);
  
  //the five overlapping sprites that make up the player's hand
  for(let i = 4; i >= 0; i--) {
    deck[i].suitSprite = this.add.sprite(400, -100, "suit", 4).setScale(2);
    deck[i].numberSprite = this.add.sprite(400, -100, "number", deck[i].number).setScale(2);
    playerhand[i] = deck[i];
  }
  
}//create

Notice I make new objects called Card. We need to define the constructor for this object.

After the create function, add this constructor.

//object constructor
function Card(n, v, s) {
  this.number = n;
  this.value = v;
  this.suit = s;
}

Finally, back in the create function, we need to add a tween timeline to animate the cards.


    //define our timeline with tween animations
    var timeline = this.tweens.createTimeline();


	timeline.add({
	  targets: [deckSprite, playerhand[0].suitSprite, playerhand[1].suitSprite, playerhand[2].suitSprite, playerhand[3].suitSprite, playerhand[4].suitSprite],
          y: 100,
	  duration: 1000,
	  ease: 'Linear'
	  });
	  
	  timeline.add({
	  targets: playerhand[0].suitSprite,
          y: 450,
	  x: 100,
	  rotation: 6.28,
	  duration: 1000,
	  delay: 500,
	  ease: 'Linear',
	  onComplete: function () {
	    playerhand[0].suitSprite.setFrame(playerhand[0].suit)
            playerhand[0].numberSprite.x = playerhand[0].suitSprite.x;
            playerhand[0].numberSprite.y = playerhand[0].suitSprite.y;
	  }
	  });
	  
	  timeline.add({
	  targets: playerhand[1].suitSprite,
          y: 450,
	  x: 250,
	  rotation: 6.28,
	  duration: 1000,
	  delay: 250,
	  offset: '-=500',
	  ease: 'Linear',
	  onComplete: function () {
	    playerhand[1].suitSprite.setFrame(playerhand[1].suit)
            playerhand[1].numberSprite.x = playerhand[1].suitSprite.x;
            playerhand[1].numberSprite.y = playerhand[1].suitSprite.y;
	  }
	  });
	  
	  timeline.add({
	  targets: playerhand[2].suitSprite,
          y: 450,
	  x: 400,
	  rotation: 6.28,
	  duration: 1000,
	  delay: 250,
	  offset: '-=500',
	  ease: 'Linear',
	  onComplete: function () {
	    playerhand[2].suitSprite.setFrame(playerhand[2].suit)
            playerhand[2].numberSprite.x = playerhand[2].suitSprite.x;
            playerhand[2].numberSprite.y = playerhand[2].suitSprite.y;
	  }
	  });
	  
	  timeline.add({
	  targets: playerhand[3].suitSprite,
          y: 450,
	  x: 550,
	  rotation: 6.28,
	  duration: 1000,
	  delay: 250,
	  offset: '-=500',
	  ease: 'Linear',
	  onComplete: function () {
	    playerhand[3].suitSprite.setFrame(playerhand[3].suit)
            playerhand[3].numberSprite.x = playerhand[3].suitSprite.x;
            playerhand[3].numberSprite.y = playerhand[3].suitSprite.y;
	  }
	  });
	  
	  timeline.add({
	  targets: playerhand[4].suitSprite,
          y: 450,
	  x: 700,
	  rotation: 6.28,
	  duration: 1000,
	  delay: 250,
	  offset: '-=500',
	  ease: 'Linear',
	  onComplete: function () {
	    playerhand[4].suitSprite.setFrame(playerhand[4].suit)
            playerhand[4].numberSprite.x = playerhand[4].suitSprite.x;
            playerhand[4].numberSprite.y = playerhand[4].suitSprite.y;
	  }
	  });
	  
	   
	  
	
    timeline.play();

And so here is the complete code.

<!doctype html> 
<html lang="en"> 

<head> 
    <meta charset="UTF-8" />
    <title>Deck of Cards</title>

    <script src="phaser.min.js"></script>
	
    <style type="text/css">

        body {
            margin: 0;
        }

    </style>
</head>

<body>

<script>

var config = {
    width: 800,
    height: 600,
	backgroundColor: '#dddddd',
    type: Phaser.AUTO,
    scene: {
        preload: preload,
        create: create
    }
};

var deck;
var playerhand;
var deckSprite;


var game = new Phaser.Game(config);

function preload ()
{
       this.load.spritesheet('suit', 'assets/suits.png', { frameWidth: 60, frameHeight: 90 });
       this.load.spritesheet('number', 'assets/numbers.png', { frameWidth: 60, frameHeight: 75 });

}

function create ()
{

  deck = [];
  playerhand = [];

  //create the deck of 52 cards
  for(let j = 0; j < 4; j++) {
    let suit = j;
    for(let i = 0; i < 13; i++) {
        let number = i;
        deck.push(new Card(number, i+2, suit));
    }
  }
  
  deck = Phaser.Utils.Array.Shuffle(deck);
  
  deckSprite = this.add.sprite(400, -100, "suit", 4).setScale(2);
  
  //the five sprites that make up the player's hand
  for(let i = 4; i >= 0; i--) {
    deck[i].suitSprite = this.add.sprite(400, -100, "suit", 4).setScale(2);
	deck[i].numberSprite = this.add.sprite(400, -100, "number", deck[i].number).setScale(2);
    playerhand[i] = deck[i];
  }
  
    //define our timeline with tween animations
    var timeline = this.tweens.createTimeline();


	timeline.add({
	  targets: [deckSprite, playerhand[0].suitSprite, playerhand[1].suitSprite, playerhand[2].suitSprite, playerhand[3].suitSprite, playerhand[4].suitSprite],
          y: 100,
	  duration: 1000,
	  ease: 'Linear'
	  });
	  
	  timeline.add({
	  targets: playerhand[0].suitSprite,
          y: 450,
	  x: 100,
	  rotation: 6.28,
	  duration: 1000,
	  delay: 500,
	  ease: 'Linear',
	  onComplete: function () {
	    playerhand[0].suitSprite.setFrame(playerhand[0].suit)
	    playerhand[0].numberSprite.x = playerhand[0].suitSprite.x;
	    playerhand[0].numberSprite.y = playerhand[0].suitSprite.y;
	  }
	  });
	  
	  timeline.add({
	  targets: playerhand[1].suitSprite,
          y: 450,
	  x: 250,
	  rotation: 6.28,
	  duration: 1000,
	  delay: 250,
	  offset: '-=500',
	  ease: 'Linear',
	  onComplete: function () {
	    playerhand[1].suitSprite.setFrame(playerhand[1].suit)
	    playerhand[1].numberSprite.x = playerhand[1].suitSprite.x;
	    playerhand[1].numberSprite.y = playerhand[1].suitSprite.y;
	  }
	  });
	  
	  timeline.add({
	  targets: playerhand[2].suitSprite,
          y: 450,
	  x: 400,
	  rotation: 6.28,
	  duration: 1000,
	  delay: 250,
	  offset: '-=500',
	  ease: 'Linear',
	  onComplete: function () {
	    playerhand[2].suitSprite.setFrame(playerhand[2].suit)
	    playerhand[2].numberSprite.x = playerhand[2].suitSprite.x;
	    playerhand[2].numberSprite.y = playerhand[2].suitSprite.y;
	  }
	  });
	  
	  timeline.add({
	  targets: playerhand[3].suitSprite,
          y: 450,
	  x: 550,
	  rotation: 6.28,
	  duration: 1000,
	  delay: 250,
	  offset: '-=500',
	  ease: 'Linear',
	  onComplete: function () {
	    playerhand[3].suitSprite.setFrame(playerhand[3].suit)
	    playerhand[3].numberSprite.x = playerhand[3].suitSprite.x;
	    playerhand[3].numberSprite.y = playerhand[3].suitSprite.y;
	  }
	  });
	  
	  timeline.add({
	  targets: playerhand[4].suitSprite,
          y: 450,
	  x: 700,
	  rotation: 6.28,
	  duration: 1000,
	  delay: 250,
	  offset: '-=500',
	  ease: 'Linear',
	  onComplete: function () {
	    playerhand[4].suitSprite.setFrame(playerhand[4].suit)
	    playerhand[4].numberSprite.x = playerhand[4].suitSprite.x;
	    playerhand[4].numberSprite.y = playerhand[4].suitSprite.y;
	  }
	  });
	  
	   
	  
	
    timeline.play();
	

}//create

//object constructor
function Card(n, v, s) {
  this.number = n;
  this.value = v;
  this.suit = s;
}


</script>

</body>
</html>


And the result is...


Thanks for reading.

Comments

Popular Posts