This script is adapted from the RPG card carousel example in the Phaser 3 Feb 2020 backer scripts.
That example used the same ellipse concept to position the cards with a second set of blurred images, and required user input to flip the cards which then proceed on straight trajectories between points on the ellipse.
This one uses pathFollower to create a smoother transition between points following the curve, and renderTexture to enable more complicated card face construction (though I only leave it as a playing card face in the example).
The order of the tweens was something it took me days to figure out. We start with a counter tween, which I couldn’t figure out how to change from decimals to integers. As a kludge, we count from 0 to the deck size minus 1, but onUpdate listen for when the decimal reaches the next integer. At that point we pause the counter, flip the first card in a yoyoing tween then rotate the cards and resume the counter. Once the rotations are done, the CONTINUE text appears.
function create() {
const tobedealt = 10, cardwidth = 73, cardheight = 98;
const ellipse = new Phaser.Curves.Ellipse({
x: 400,
y: 270,
rotation: 90,
xRadius: 100,
yRadius: 250
});
let points = ellipse.getPoints(tobedealt);
if (360 % tobedealt == 0)
points.pop();
let showcard = [];
points.forEach((p, i) => {
showcard.push(this.add.renderTexture(-1000, -1000, cardwidth, cardheight));
showcard[i].draw(this.add.sprite(0, 0, 'fronts', tobedealt - i - 1)
.setOrigin(0).setVisible(false).setDisplaySize(cardwidth, cardheight));
});
const minY = ellipse.y-ellipse.xRadius;
const maxY = ellipse.y+ellipse.xRadius;
const scaleRange = 0.3 / (maxY - minY);
const path = new Phaser.Curves.Path();
path.add(ellipse);
let dealtcard = [];
points.forEach((p, i, arr) => {
var pointinpoint = points[Object.keys(points).length - i];
if (i == 0)
pointinpoint = points[0];
dealtcard.push(this.add.follower(path, pointinpoint.x, pointinpoint.y, 'fronts',i+26)
.setDisplaySize(cardwidth, cardheight).setOrigin(0.5, 1)
.setDepth(p.y)
.setScale(0.7 + scaleRange * (pointinpoint.y - minY))
);
});
let contbutt = this.add.text(400, 420, "CONTINUE").setOrigin(0.5).setVisible(false);
let iter = 0;
const cardgap = 1 / tobedealt, initialdelay = 2000, spintime = 300, rotatetime = 1000;
const durationtime = tobedealt * (spintime*2 + rotatetime);
let cardcarousel = this.tweens.addCounter({
from: 0,
to: tobedealt - 1,
delay: initialdelay,
duration: durationtime,
callbackScope: this,
onUpdate: (tween) => {
if (tween.getValue() >= iter)
{
cardcarousel.pause();
let cardtoflip = iter;
this.tweens.add({
targets: dealtcard[cardtoflip],
scaleX: 0,
duration: spintime,
ease:'Quad.easeOut',
yoyo: true,
callbackScope: this,
onYoyo: () => {
dealtcard[cardtoflip].setTexture(showcard[tobedealt-cardtoflip-1].texture);
},
onComplete: () => {
if (iter < tobedealt)
dealtcard.forEach((thiscard, cpos) => {
let startpathpoint = cardgap * (iter - cpos - 1);
let endpathpoint = startpathpoint + cardgap;
if (startpathpoint >= 1)
{
startpathpoint -= 1;
endpathpoint -= 1;
}
else if (startpathpoint < 0)
{
startpathpoint += 1;
endpathpoint += 1;
}
thiscard.startFollow({
duration: rotatetime,
repeat: 0,
rotateToPath: false,
positionOnPath: true,
from: startpathpoint,
to: endpathpoint,
ease:'Quad.easeOut',
onUpdate: () => {
thiscard.setDepth(thiscard.y);
thiscard.setScale(0.7 + scaleRange * (thiscard.y - minY));
}
});
})
else
contbutt.setVisible(true);
}
});
iter++;
cardcarousel.resume();
}
}
});
}









Leave a Reply