Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about Legends of Runeterra game, Game development, HTML5, Javascript and Phaser.

Are you destroying enemies in Legends of Runeterra? I am a Platinum player at the moment, and I am enjoying it a lot.

I play mostly on my iPhone, and love the way the game shows the cards in your hand, in the bottom right part of the screen.

So I played a bit with Phaser drag listeners and I managed to create something similar in HTML5.

The whole card drawing process is going to be quite complex, so I decided to break it into steps. In this first step, we’ll see how to display cards in our hand, select them and move them around the screen.

Have a look:

Click/tap and drag a card, then release it and see it flying back in the deck.

Everything is managed by drag listeners and tweens, as you can see from the source code:

let game;
let gameOptions = {
	startingCards: 5,
	cardWidth: 265,
	cardHeight: 400,
	cardDistance: 50,
	cardAngle: 5
}
window.onload = function() {
    let gameConfig = {
        type: Phaser.AUTO,
        scale: {
            mode: Phaser.Scale.FIT,
            autoCenter: Phaser.Scale.CENTER_BOTH,
            parent: "thegame",
            width: 1280,
            height: 740
        },
        scene: playGame
    }
    game = new Phaser.Game (gameConfig);
    window.focus();
}
class playGame extends Phaser.Scene{
    constructor() {
        super("PlayGame");
    }
    preload() {
		this.load.image("background", "background.png");
        this.load.spritesheet("cards", "cards.png", {
            frameWidth: gameOptions.cardWidth,
            frameHeight: gameOptions.cardHeight
        });
    }
    create() {
		this.handArray = [];
		this.background = this.add.sprite(game.config.width / 2, game.config.height / 2, "background")
		let startAngle = - gameOptions.cardAngle
        for(let i = 0; i < gameOptions.startingCards; i ++) {
			let card = this.add.sprite(game.config.width - i * gameOptions.cardDistance, game.config.height, "cards", i);
			card.setInteractive({
				draggable: true
			});
			card.displayWidth = gameOptions.cardWidth / 2;
			card.displayHeight = gameOptions.cardHeight / 2;
			this.handArray.push(card);
			card.setOrigin(0.5, 1);
			card.setDepth(gameOptions.startingCards - i);
			card.angle = startAngle;
			if(i > 0){
				card.angle = this.handArray[i - 1].angle + startAngle;
				startAngle *= 0.9;
				let cardTop = card.getBounds().top
				let previousCardTop = this.handArray[i - 1].getBounds().top;
				card.y += (previousCardTop - cardTop) * 1.6;
			}
			card.startPosition = {
				angle: card.angle,
				x: card.x,
				y: card.y
			}
		}
		this.input.on("dragstart", function(pointer, gameObject) {
			this.tweens.add({
            	targets: gameObject,
            	angle: 0,
				x: pointer.x,
				y: pointer.y,
				displayWidth: gameOptions.cardWidth,
				displayHeight: gameOptions.cardHeight,
				duration: 150
	        });
			this.tweens.add({
            	targets: this.background,
            	alpha: 0.3,
				duration: 150
	        });
		}, this);
		this.input.on("drag", function(pointer, gameObject, dragX, dragY){
			gameObject.x = pointer.x;
			gameObject.y = pointer.y ;
		});
		this.input.on("dragend", function(pointer, gameObject, dropped){
			this.tweens.add({
	        	targets: gameObject,
	        	angle: gameObject.startPosition.angle,
				x: gameObject.startPosition.x,
				y: gameObject.startPosition.y,
				displayWidth: gameOptions.cardWidth / 2,
				displayHeight: gameOptions.cardHeight / 2,
				duration: 150
			});
			this.tweens.add({
            	targets: this.background,
            	alpha: 1,
				duration: 150
	        });
		}, this);
    }
}

The code is uncommented because there is still a lot to do, but hey, it looks like the original mobile game. Next time, we’ll see how to drop cards in the game field, I am going to add comments to the code and explain how drag and drop works in Phaser. Download the source code.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.