Pong con Phaser

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.

Poner imagen de fondo

Cargamos la imagen de fondo de la escena principal.

Poner la pelota en pantalla

class Pong extends Phaser.Scene {
    preload() {
        ...
        this.load.spritesheet('ball', ball, {frameWidth: 100, frameHeight:100});
    }

    create() {
        ...
        this.ball= this.physics.add.sprite(gameWidth/2, gameHeight/2, 'ball');
        this.anims.create({
            key: 'shine',
            frames: this.anims.generateFrameNumbers('ball', { start: 0, end: 3 }),
            frameRate: 10,
            repeat: -1
        });
        this.ball.play('shine');
    }
}
const config = {
    ...
    physics: {
        default: 'arcade',
    },
}

La pelota gira

update(){
    this.ball.rotation += 0.1;
}

La pelota se mueve

create(){
	this.speed = 500;
	this.placeBall();
}

placeBall() {
	this.ball.x = gameWidth/2;
	this.ball.y = gameHeight/2;
	let initialAngle = Math.random() * (Math.PI/4 *3 - Math.PI/4)+ Math.PI/4;
	const leftOrRight = Math.floor(Math.random()*2);
	if(leftOrRight === 1)initialAngle = initialAngle + Math.PI;
	const vx = Math.sin(initialAngle ) * this.speed;
	const vy = Math.cos(initialAngle ) * this.speed;
	this.ball.body.velocity.x = vx;
	this.ball.body.velocity.y = vy;
}

Rebote contra las paredes

this.ball.setBounce(1);
this.ball.setCollideWorldBounds(true);

Poner un jugador

this.load.image('hand1', hand1);
this.hand1 = this.physics.add.sprite(70, 320, 'hand1');

Mover al jugador con el teclado

create(){
	...
	this.cursors = this.input.keyboard.createCursorKeys();
}

update() {
	...
	if (this.cursors.up.isDown) {
		this.hand1.y = this.hand1.y - 5;
	} else if (this.cursors.down.isDown) {
		this.hand1.y = this.hand1.y + 5;
	}
}

Controles visuales

this.load.image('arrow', arrow);
this.visualControls({ x: 50, y :50 },{ x :50, y :590 }, this.hand1);
visualControls(btn1, btn2, player) {
	const upbtn = this.add.sprite(btn1.x,btn1.y, 'arrow').setInteractive();
	const downbtn = this.add.sprite(btn2.x, btn2.y, 'arrow').setInteractive();
	downbtn.flipY = true;
}

Funcionalidad de los controles visuales

visualControls(btn1, btn2, player) {
	...
	player.setData('verticalDirection', 0);
	downbtn.on('pointerdown', () => {
		player.setData('verticalDirection', -1);
	});
	upbtn.on('pointerdown', () => {
		player.setData('verticalDirection', 1);
	});
	downbtn.on('pointerup', () => {
		player.setData('verticalDirection', 0);
	});
	upbtn.on('pointerup', () => {
		player.setData('verticalDirection', 0);
	});
}

update(){
	...
	if (this.cursors.up.isDown || this.hand1.getData('verticalDirection') === 1) {
		this.hand1.y = this.hand1.y - 5;
	} else if (this.cursors.down.isDown || this.hand1.getData('verticalDirection') === -1) {
		this.hand1.y = this.hand1.y + 5;
	}
}	

Colisión con el player

this.physics.add.collider(this.ball, this.hand1);

Ladrillo inamovible

this.hand1.body.immovable = true;

Dos jugadores

create(){
	...
	this.hand2 = this.physics.add.sprite(882, 320, 'hand2');
	this.visualControls({x: 910, y: 50}, {x: 910, y: 590}, this.hand2);
	this.physics.add.collider(this.ball, this.hand2);
	this.hand2.body.immovable = true;
	this.cursors2 = this.input.keyboard.addKeys({ up: 'W', left: 'A', down: 'S', right: 'D' });
}

update(){
	...
	if (this.cursors2.up.isDown || this.hand2.getData('verticalDirection') === 1) {
		this.hand2.y = this.hand2.y - 5;
	}else if (this.cursors2.down.isDown || 		
		this.hand2.getData('verticalDirection') === -1) {
		this.hand2.y = this.hand2.y + 5;
	}
}

Problema controles táctiles para varios jugadores

Por defecto Phaser solo detecta la pulsación sobre la pantalla de un único dedo. Esto quiere decir que si el usuario pulsa sobre la pantalla con varios dedos a la vez, solo la primera pulsación será detectada. Afortunadamente, añadir puntos de detección sobre la pantalla es muy fácil.

Debemos añadir al principio del método create la siguiente línea.

this.input.addPointer();

La añadiremos tantas veces como puntos de detección queramos. Como ya tenemos un punto de detección sobre la pantalla, si la añadimos una vez, realmente ahora tendríamos dos puntos de detección. En este juego he decidido que quería cuatro puntos de detección, así que he añadido la línea tres veces:

create() {
	...
	this.input.addPointer();
	this.input.addPointer();
	this.input.addPointer();
}

Perder

create(){
	...
	this.physics.world.setBoundsCollision(false, false, true, true);
}

update(){
	...
	if (this.ball.x < 0) {
		alert('player1 has perdido');
	} else if (this.ball.x > gameWidth) {
		alert('player2 has perdido');
	}
}

Escena de fin de juego

Creamos la escena a la que iremos cuando perdamos.

Poner marcador

this.showScore();
showScore() {
    this.hand1Score = this.add.text(395, 75, '0', {fontFamily: 'font1', fontSize: 80, color: '#ffffff', align: 'right'}).setOrigin(1, 0);
    this.hand2Score = this.add.text(520, 75, '0', {fontFamily: 'font1', fontSize: 80, color: '#ffffff'});
}

Aumentar el marcador

this.hand1Score.setText(parseInt(this.hand1Score.text) + 1);

Ajustar areas de colisión

this.hand1.setSize(60, 250);

Limitar el rango de movimiento de las manos

this.hand1.setCollideWorldBounds(true);

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.