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

class Escena extends Phaser.Scene {
    preload() {
        this.load.image('fondo', '../img/fondo.jpg');
    }
    create() {
        this.add.sprite(480, 320, 'fondo');
    }
}

Poner la pelota en pantalla

class Escena extends Phaser.Scene {
    preload() {
        ...
        this.load.spritesheet('bola', '../img/bola.png',{frameWidth: 100, frameHeight:100});
    }
    create() {
        ...
        this.bola = this.physics.add.sprite(480, 320, 'bola');
        this.anims.create({
            key: 'brillar',
            frames: this.anims.generateFrameNumbers('bola', { start: 0, end: 3 }),
            frameRate: 10,
            repeat: -1
        });
        this.bola.play('brillar');
    }
}
const config = {
    ...
    physics: {
        default: 'arcade',
    },
}

La pelota gira

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

La pelota se mueve

create() {
    ...
    let anguloInicial = Math.PI/4;
    const velocidad = 500;
    const vx = Math.cos(anguloInicial) * velocidad;
    const vy = Math.sin(anguloInicial) * velocidad;
    this.bola.body.velocity.x = vx;
    this.bola.body.velocity.y = vy;
}

La pelota se mueve con un ángulo aleatorio correcto

let anguloInicial = Math.PI / 4 - Math.random() * Math.PI / 2;

const derechaOIzq = Math.floor(Math.random()*2);
if(derechaOIzq === 1)anguloInicial = anguloInicial + Math.PI;

Rebote contra las paredes

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

Poner un jugador

this.load.image('mano1', '../img/mano1.png');
this.mano1 = this.physics.add.sprite(70, 320, 'mano1');

Mover al jugador con el teclado

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

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

Controles visuales

this.load.image('leftbtn', '../img/flecha.png');
this.controlesVisuales({ x: 50, y :50 },{ x :50, y :590 }, this.mano1);
controlesVisuales(btn1, btn2, player) {
	const upbtn = this.add.sprite(btn1.x,btn1.y, 'leftbtn').setInteractive();
	const downbtn = this.add.sprite(btn2.x, btn2.y, 'leftbtn').setInteractive();
	downbtn.flipY = true;
}

Funcionalidad de los controles visuales

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

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

Colisión con el player

this.physics.add.collider(this.bola, this.mano1);

Ladrillo inamovible

this.mano1.body.immovable = true;

Dos jugadores

this.mano2 = this.physics.add.sprite(882, 320, 'mano2');
this.controlesVisuales({x: 910, y: 50}, {x: 910, y: 590}, this.mano2);
this.physics.add.collider(this.bola, this.mano2);
this.mano2.body.immovable = true;
if (this.cursors.up.isDown || this.mano2.getData('direccionVertical') === 1) {
	this.mano2.y = this.mano2.y - 5;
}else if (this.cursors.down.isDown || this.mano2.getData('direccionVertical') === -1) {
	this.mano2.y = this.mano2.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.bola.setCollideWorldBounds(true);
	this.physics.world.setBoundsCollision(false, false, true, true);
}

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

Volver a jugar

colocarPelota() {
	this.bola.x = 480;
	this.bola.y = 320;
	let anguloInicial = Math.random() * (Math.PI/4 *3 - Math.PI/4)+ Math.PI/4;
	const derechaOIzq = Math.floor(Math.random()*2);
	if(derechaOIzq === 1)anguloInicial = anguloInicial + Math.PI;
	const vx = Math.sin(anguloInicial) * this.velocidad;
	const vy = Math.cos(anguloInicial) * this.velocidad;
	this.bola.body.velocity.x = vx;
	this.bola.body.velocity.y = vy;
}

Poner marcador

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

Aumentar el marcador

this.marcadorMano2.text = parseInt(this.marcadorMano2.text) + 1;

Ajustar areas de colisión

this.mano1.setSize(60, 250);

Limitar el rango de movimiento de las manos

this.mano1.setCollideWorldBounds(true);
← Flappy Bird con Phaser
Physics Editor →