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