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.
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>
Thanks for reading.
Comments
Post a Comment