Phaser引擎开发:用户输入与交互_案例分析与实践

案例分析与实践

在上一节中,我们介绍了如何在Phaser引擎中处理用户输入的基本方法。现在,我们将通过具体的案例来深入理解和实践用户输入与交互的实现。通过这些案例,你将能够掌握更复杂的输入处理技术,如多点触控、游戏手柄支持、键盘和鼠标组合输入等。

案例1:实现一个简单的射击游戏

1.1 游戏目标

实现一个简单的射击游戏,玩家可以通过鼠标点击屏幕来发射子弹,击中移动的敌人目标。

1.2 代码实现

首先,我们需要创建一个Phaser游戏实例,并设置基本的游戏场景。


// 引入Phaser引擎

import Phaser from 'phaser';



// 创建游戏配置

const config = {

    type: Phaser.AUTO,

    width: 800,

    height: 600,

    physics: {

        default: 'arcade',

        arcade: {

            gravity: { y: 0 },

            debug: false

        }

    },

    scene: {

        preload: preload,

        create: create,

        update: update

    }

};



// 创建游戏实例

const game = new Phaser.Game(config);



// 预加载资源

function preload() {

    this.load.image('player', 'assets/player.png');

    this.load.image('bullet', 'assets/bullet.png');

    this.load.image('enemy', 'assets/enemy.png');

}



// 创建游戏场景

function create() {

    // 创建玩家

    this.player = this.physics.add.sprite(400, 500, 'player');

    this.player.setCollideWorldBounds(true);



    // 创建子弹组

    this.bullets = this.physics.add.group({

        key: 'bullet',

        maxSize: 10,

        runChildUpdate: true

    });



    // 创建敌人组

    this.enemies = this.physics.add.group({

        key: 'enemy',

        runChildUpdate: true

    });



    // 生成敌人

    for (let i = 0; i < 10; i++) {

        const enemy = this.enemies.create(Phaser.Math.Between(50, 750), Phaser.Math.Between(50, 150), 'enemy');

        enemy.setVelocity(Phaser.Math.Between(-200, 200), Phaser.Math.Between(100, 300));

        enemy.setCollideWorldBounds(true);

        enemy.setBounce(1);

    }



    // 设置玩家射击

    this.input.on('pointerdown', this.shootBullet, this);

}



// 更新游戏场景

function update(time, delta) {

    // 更新子弹

    this.bullets.children.iterate(function (bullet) {

        if (bullet.active) {

            bullet.setVelocityY(-400);

        }

    });



    // 检测碰撞

    this.physics.add.collider(this.bullets, this.enemies, this.hitEnemy, null, this);

}



// 射击子弹

function shootBullet(pointer) {

    const bullet = this.bullets.get();

    if (bullet) {

        bullet.setActive(true);

        bullet.setVisible(true);

        bullet.setPosition(this.player.x, this.player.y);

    }

}



// 敌人被击中

function hitEnemy(bullet, enemy) {

    bullet.setActive(false);

    bullet.setVisible(false);

    enemy.destroy();

}

1.3 代码解释

  1. 预加载资源

    • this.load.image 方法用于加载图像资源,这里我们加载了玩家、子弹和敌人的图像。
  2. 创建游戏场景

    • this.player 创建了一个玩家角色,使用 setCollideWorldBounds 方法确保玩家不会移出屏幕边界。

    • this.bulletsthis.enemies 分别创建了子弹和敌人的物理组,maxSize 设置了子弹组的最大大小,runChildUpdate 允许子对象在每一帧更新时运行更新函数。

    • 使用 for 循环生成10个敌人,每个敌人随机移动速度和方向,使用 setCollideWorldBoundssetBounce 方法确保敌人在屏幕内反弹。

  3. 设置玩家射击

    • this.input.on 用于监听鼠标点击事件,当点击屏幕时调用 this.shootBullet 方法。
  4. 更新游戏场景

    • this.bullets.children.iterate 遍历子弹组中的每个子弹,设置其垂直速度使其向上飞行。

    • this.physics.add.collider 用于检测子弹和敌人之间的碰撞,当发生碰撞时调用 this.hitEnemy 方法。

  5. 射击子弹

    • this.bullets.get 从子弹组中获取一个未活跃的子弹,设置其状态为活跃并显示在屏幕上,位置为玩家的位置。
  6. 敌人被击中

    • bullet.setActive(false)bullet.setVisible(false) 使子弹失效并隐藏。

    • enemy.destroy() 销毁敌人对象。

案例2:实现多点触控支持

2.1 游戏目标

实现一个支持多点触控的游戏,玩家可以通过触摸屏幕上的多个点来控制多个角色的移动。

2.2 代码实现


// 引入Phaser引擎

import Phaser from 'phaser';



// 创建游戏配置

const config = {

    type: Phaser.AUTO,

    width: 800,

    height: 600,

    physics: {

        default: 'arcade',

        arcade: {

            gravity: { y: 0 },

            debug: false

        }

    },

    scene: {

        preload: preload,

        create: create,

        update: update

    }

};



// 创建游戏实例

const game = new Phaser.Game(config);



// 预加载资源

function preload() {

    this.load.image('player', 'assets/player.png');

}



// 创建游戏场景

function create() {

    // 创建角色组

    this.players = this.physics.add.group({

        key: 'player',

        runChildUpdate: true

    });



    // 生成角色

    for (let i = 0; i < 5; i++) {

        const player = this.players.create(100 + i * 100, 500, 'player');

        player.setCollideWorldBounds(true);

    }



    // 设置多点触控

    this.input acknowlegeFirstPointer = false;

    this.input.on('pointerdown', this.handleTouch, this);

    this.input.on('pointerup', this.handleTouch, this);

    this.input.on('pointermove', this.handleTouch, this);

}



// 更新游戏场景

function update(time, delta) {

    // 更新角色

    this.players.children.iterate(function (player) {

        if (player.active) {

            player.body.setVelocity(0);

        }

    });

}



// 处理触摸事件

function handleTouch(pointer) {

    if (pointer.isDown) {

        // 查找最近的角色

        const closestPlayer = this.findClosestPlayer(pointer.x, pointer.y);

        if (closestPlayer) {

            closestPlayer.setVelocityX(Phaser.Math.Between(-200, 200));

            closestPlayer.setVelocityY(Phaser.Math.Between(-200, 200));

        }

    } else {

        // 停止角色移动

        this.players.children.iterate(function (player) {

            player.body.setVelocity(0);

        });

    }

}



// 查找最近的角色

function findClosestPlayer(x, y) {

    let closestPlayer = null;

    let closestDistance = Infinity;



    this.players.children.iterate(function (player) {

        const distance = Phaser.Math.Distance.Between(player.x, player.y, x, y);

        if (distance < closestDistance) {

            closestDistance = distance;

            closestPlayer = player;

        }

    });



    return closestPlayer;

}

2.3 代码解释

  1. 预加载资源

    • this.load.image 方法用于加载玩家的图像资源。
  2. 创建游戏场景

    • this.players 创建了一个角色组,runChildUpdate 允许子对象在每一帧更新时运行更新函数。

    • 使用 for 循环生成5个角色,每个角色的初始位置不同,确保它们不会重叠。

    • this.input.acknowledgeFirstPointer = false; 设置多点触控支持。

    • this.input.on 用于监听触摸事件,包括 pointerdownpointeruppointermove

  3. 更新游戏场景

    • this.players.children.iterate 遍历角色组中的每个角色,停止其移动。
  4. 处理触摸事件

    • pointer.isDown 判断触摸点是否按下,如果是则调用 findClosestPlayer 方法查找最近的角色并设置其移动速度。

    • pointer.isUp 判断触摸点是否抬起,如果是则停止所有角色的移动。

  5. 查找最近的角色

    • Phaser.Math.Distance.Between 方法用于计算两个点之间的距离,查找离触摸点最近的角色并返回。

案例3:实现游戏手柄支持

3.1 游戏目标

实现一个支持游戏手柄的游戏,玩家可以通过手柄控制角色的移动和射击。

3.2 代码实现


// 引入Phaser引擎

import Phaser from 'phaser';



// 创建游戏配置

const config = {

    type: Phaser.AUTO,

    width: 800,

    height: 600,

    physics: {

        default: 'arcade',

        arcade: {

            gravity: { y: 0 },

            debug: false

        }

    },

    scene: {

        preload: preload,

        create: create,

        update: update

    }

};



// 创建游戏实例

const game = new Phaser.Game(config);



// 预加载资源

function preload() {

    this.load.image('player', 'assets/player.png');

    this.load.image('bullet', 'assets/bullet.png');

}



// 创建游戏场景

function create() {

    // 创建玩家

    this.player = this.physics.add.sprite(400, 500, 'player');

    this.player.setCollideWorldBounds(true);



    // 创建子弹组

    this.bullets = this.physics.add.group({

        key: 'bullet',

        maxSize: 10,

        runChildUpdate: true

    });



    // 初始化游戏手柄

    this.input.gamepad.once('connected', (pad) => {

        this.pad = pad;

    });



    // 设置玩家移动

    this.input.gamepad.on('down', this.handleGamepad, this);

    this.input.gamepad.on('up', this.handleGamepad, this);

}



// 更新游戏场景

function update(time, delta) {

    // 检查手柄连接状态

    if (this.pad) {

        // 移动玩家

        this.player.setVelocity(0);

        if (this.pad.axes[0].value !== 0) {

            this.player.setVelocityX(this.pad.axes[0].value * 200);

        }

        if (this.pad.axes[1].value !== 0) {

            this.player.setVelocityY(this.pad.axes[1].value * 200);

        }



        // 射击

        if (this.pad.A) {

            this.shootBullet();

        }

    }



    // 更新子弹

    this.bullets.children.iterate(function (bullet) {

        if (bullet.active) {

            bullet.setVelocityY(-400);

        }

    });



    // 检测碰撞

    this.physics.add.collider(this.bullets, this.enemies, this.hitEnemy, null, this);

}



// 处理游戏手柄事件

function handleGamepad(button, pad, duration, value) {

    if (button.index === 0 && value) {

        this.shootBullet();

    }

}



// 射击子弹

function shootBullet() {

    const bullet = this.bullets.get();

    if (bullet) {

        bullet.setActive(true);

        bullet.setVisible(true);

        bullet.setPosition(this.player.x, this.player.y);

    }

}



// 敌人被击中

function hitEnemy(bullet, enemy) {

    bullet.setActive(false);

    bullet.setVisible(false);

    enemy.destroy();

}

4.3 代码解释(续)

  1. 更新游戏场景

    • this.player.setVelocity(0); 用于重置玩家的移动速度,确保在没有按键按下时玩家停止移动。

    • if (this.cursors.left.isDown) { this.player.setVelocityX(-200); } 判断左箭头键是否按下,如果是则设置玩家的水平速度为-200,使其向左移动。

    • else if (this.cursors.right.isDown) { this.player.setVelocityX(200); } 判断右箭头键是否按下,如果是则设置玩家的水平速度为200,使其向右移动。

    • if (this.cursors.up.isDown) { this.player.setVelocityY(-200); } 判断上箭头键是否按下,如果是则设置玩家的垂直速度为-200,使其向上移动。

    • else if (this.cursors.down.isDown) { this.player.setVelocityY(200); } 判断下箭头键是否按下,如果是则设置玩家的垂直速度为200,使其向下移动。

    • this.bullets.children.iterate 遍历子弹组中的每个子弹,设置其垂直速度使其向上飞行。

    • this.physics.add.collider 用于检测子弹和敌人之间的碰撞,当发生碰撞时调用 this.hitEnemy 方法。

  2. 射击子弹

    • this.bullets.get 从子弹组中获取一个未活跃的子弹,设置其状态为活跃并显示在屏幕上,位置为玩家的位置。

    • bullet.setVelocity(Phaser.Math.Normalize(Phaser.Math.Vector2.FromAngle(this.player.angle, 400))); 用于根据玩家的朝向设置子弹的初始速度,使其沿玩家的朝向发射。

  3. 更新角色朝向

    • const dx = pointer.x - this.player.x; 计算鼠标指针与玩家角色在水平方向上的差值。

    • const dy = pointer.y - this.player.y; 计算鼠标指针与玩家角色在垂直方向上的差值。

    • this.player.angle = Phaser.Math.RAD_TO_DEG * Math.atan2(dy, dx); 使用 Math.atan2 计算玩家角色与鼠标指针之间的角度,并将其转换为度数,设置玩家角色的朝向。

  4. 敌人被击中

    • bullet.setActive(false)bullet.setVisible(false) 使子弹失效并隐藏。

    • enemy.destroy() 销毁敌人对象。

案例5:实现更复杂的组合输入

5.1 游戏目标

实现一个支持键盘、鼠标和游戏手柄组合输入的游戏,玩家可以通过键盘控制角色的移动,通过鼠标点击发射子弹,通过鼠标移动调整角色的朝向,同时可以通过游戏手柄进行同样的操作。

5.2 代码实现


// 引入Phaser引擎

import Phaser from 'phaser';



// 创建游戏配置

const config = {

    type: Phaser.AUTO,

    width: 800,

    height: 600,

    physics: {

        default: 'arcade',

        arcade: {

            gravity: { y: 0 },

            debug: false

        }

    },

    scene: {

        preload: preload,

        create: create,

        update: update

    }

};



// 创建游戏实例

const game = new Phaser.Game(config);



// 预加载资源

function preload() {

    this.load.image('player', 'assets/player.png');

    this.load.image('bullet', 'assets/bullet.png');

}



// 创建游戏场景

function create() {

    // 创建玩家

    this.player = this.physics.add.sprite(400, 500, 'player');

    this.player.setCollideWorldBounds(true);



    // 创建子弹组

    this.bullets = this.physics.add.group({

        key: 'bullet',

        maxSize: 10,

        runChildUpdate: true

    });



    // 初始化键盘输入

    this.cursors = this.input.keyboard.createCursorKeys();



    // 初始化游戏手柄

    this.input.gamepad.once('connected', (pad) => {

        this.pad = pad;

    });



    // 设置射击

    this.input.on('pointerdown', this.shootBullet, this);

    this.input.gamepad.on('down', this.handleGamepad, this);



    // 设置角色朝向

    this.input.on('pointermove', this.updatePlayerDirection, this);

}



// 更新游戏场景

function update(time, delta) {

    // 移动玩家

    this.player.setVelocity(0);

    if (this.cursors.left.isDown || (this.pad && this.pad.axes[0].value < -0.5)) {

        this.player.setVelocityX(-200);

    } else if (this.cursors.right.isDown || (this.pad && this.pad.axes[0].value > 0.5)) {

        this.player.setVelocityX(200);

    }

    if (this.cursors.up.isDown || (this.pad && this.pad.axes[1].value < -0.5)) {

        this.player.setVelocityY(-200);

    } else if (this.cursors.down.isDown || (this.pad && this.pad.axes[1].value > 0.5)) {

        this.player.setVelocityY(200);

    }



    // 更新子弹

    this.bullets.children.iterate(function (bullet) {

        if (bullet.active) {

            bullet.setVelocityY(-400);

        }

    });



    // 检测碰撞

    this.physics.add.collider(this.bullets, this.enemies, this.hitEnemy, null, this);

}



// 射击子弹

function shootBullet(pointer) {

    const bullet = this.bullets.get();

    if (bullet) {

        bullet.setActive(true);

        bullet.setVisible(true);

        bullet.setPosition(this.player.x, this.player.y);

        bullet.setVelocity(Phaser.Math.Normalize(Phaser.Math.Vector2.FromAngle(this.player.angle, 400)));

    }

}



// 更新角色朝向

function updatePlayerDirection(pointer) {

    const dx = pointer.x - this.player.x;

    const dy = pointer.y - this.player.y;

    this.player.angle = Phaser.Math.RAD_TO_DEG * Math.atan2(dy, dx);

}



// 处理游戏手柄事件

function handleGamepad(button, pad, duration, value) {

    if (button.index === 0 && value) {

        this.shootBullet();

    }

}



// 敌人被击中

function hitEnemy(bullet, enemy) {

    bullet.setActive(false);

    bullet.setVisible(false);

    enemy.destroy();

}

5.3 代码解释

  1. 预加载资源

    • this.load.image 方法用于加载玩家和子弹的图像资源。
  2. 创建游戏场景

    • this.player 创建了一个玩家角色,使用 setCollideWorldBounds 方法确保玩家不会移出屏幕边界。

    • this.bullets 创建了子弹组,maxSize 设置了子弹组的最大大小,runChildUpdate 允许子对象在每一帧更新时运行更新函数。

    • this.input.keyboard.createCursorKeys() 用于初始化键盘输入,包括上下左右键。

    • this.input.gamepad.once('connected', (pad) => { this.pad = pad; }); 用于监听手柄连接事件并初始化手柄。

    • this.input.on('pointerdown', this.shootBullet, this); 用于监听鼠标点击事件,当点击屏幕时调用 this.shootBullet 方法。

    • this.input.gamepad.on('down', this.handleGamepad, this); 用于监听手柄按钮按下事件,当按下A按钮时调用 this.shootBullet 方法。

    • this.input.on('pointermove', this.updatePlayerDirection, this); 用于监听鼠标移动事件,当鼠标移动时调用 this.updatePlayerDirection 方法。

  3. 更新游戏场景

    • this.player.setVelocity(0); 用于重置玩家的移动速度,确保在没有按键按下时玩家停止移动。

    • if (this.cursors.left.isDown || (this.pad && this.pad.axes[0].value < -0.5)) { this.player.setVelocityX(-200); } 判断左箭头键或手柄左摇杆是否向左偏移,如果是则设置玩家的水平速度为-200,使其向左移动。

    • else if (this.cursors.right.isDown || (this.pad && this.pad.axes[0].value > 0.5)) { this.player.setVelocityX(200); } 判断右箭头键或手柄左摇杆是否向右偏移,如果是则设置玩家的水平速度为200,使其向右移动。

    • if (this.cursors.up.isDown || (this.pad && this.pad.axes[1].value < -0.5)) { this.player.setVelocityY(-200); } 判断上箭头键或手柄左摇杆是否向上偏移,如果是则设置玩家的垂直速度为-200,使其向上移动。

    • else if (this.cursors.down.isDown || (this.pad && this.pad.axes[1].value > 0.5)) { this.player.setVelocityY(200); } 判断下箭头键或手柄左摇杆是否向下偏移,如果是则设置玩家的垂直速度为200,使其向下移动。

    • this.bullets.children.iterate 遍历子弹组中的每个子弹,设置其垂直速度使其向上飞行。

    • this.physics.add.collider 用于检测子弹和敌人之间的碰撞,当发生碰撞时调用 this.hitEnemy 方法。

  4. 射击子弹

    • this.bullets.get 从子弹组中获取一个未活跃的子弹,设置其状态为活跃并显示在屏幕上,位置为玩家的位置。

    • bullet.setVelocity(Phaser.Math.Normalize(Phaser.Math.Vector2.FromAngle(this.player.angle, 400))); 用于根据玩家的朝向设置子弹的初始速度,使其沿玩家的朝向发射。

  5. 更新角色朝向

    • const dx = pointer.x - this.player.x; 计算鼠标指针与玩家角色在水平方向上的差值。

    • const dy = pointer.y - this.player.y; 计算鼠标指针与玩家角色在垂直方向上的差值。

    • this.player.angle = Phaser.Math.RAD_TO_DEG * Math.atan2(dy, dx); 使用 Math.atan2 计算玩家角色与鼠标指针之间的角度,并将其转换为度数,设置玩家角色的朝向。

  6. 处理游戏手柄事件

    • button.index === 0 && value 判断A按钮是否按下,如果是则调用 this.shootBullet 方法发射子弹。
  7. 敌人被击中

    • bullet.setActive(false)bullet.setVisible(false) 使子弹失效并隐藏。

    • enemy.destroy() 销毁敌人对象。

通过这些案例,你已经掌握了在Phaser引擎中处理用户输入的多种方法,包括鼠标、键盘、游戏手柄以及多点触控。这些技术可以灵活组合,以实现更复杂和丰富的游戏交互体验。希望这些案例对你在开发游戏时有所帮助!## 案例3:实现游戏手柄支持(续)

3.3 代码解释

  1. 预加载资源

    • this.load.image 方法用于加载玩家和子弹的图像资源。
  2. 创建游戏场景

    • this.player 创建了一个玩家角色,使用 setCollideWorldBounds 方法确保玩家不会移出屏幕边界。

    • this.bullets 创建了子弹组,maxSize 设置了子弹组的最大大小,runChildUpdate 允许子对象在每一帧更新时运行更新函数。

    • this.input.gamepad.once('connected', (pad) => { this.pad = pad; }); 用于监听手柄连接事件并初始化手柄。

    • this.input.gamepad.on('down', this.handleGamepad, this); 用于监听手柄按钮按下事件,当按下A按钮时调用 this.handleGamepad 方法。

  3. 更新游戏场景

    • this.player.setVelocity(0); 用于重置玩家的移动速度,确保在没有按键按下时玩家停止移动。

    • if (this.pad.axes[0].value !== 0) { this.player.setVelocityX(this.pad.axes[0].value * 200); } 判断手柄左摇杆在水平方向上的值,如果非零则设置玩家的水平速度。

    • if (this.pad.axes[1].value !== 0) { this.player.setVelocityY(this.pad.axes[1].value * 200); } 判断手柄左摇杆在垂直方向上的值,如果非零则设置玩家的垂直速度。

    • if (this.pad.A) { this.shootBullet(); } 判断A按钮是否按下,如果是则调用 this.shootBullet 方法发射子弹。

    • this.bullets.children.iterate 遍历子弹组中的每个子弹,设置其垂直速度使其向上飞行。

    • this.physics.add.collider 用于检测子弹和敌人之间的碰撞,当发生碰撞时调用 this.hitEnemy 方法。

  4. 射击子弹

    • this.bullets.get 从子弹组中获取一个未活跃的子弹,设置其状态为活跃并显示在屏幕上,位置为玩家的位置。

    • bullet.setVelocity(Phaser.Math.Normalize(Phaser.Math.Vector2.FromAngle(this.player.angle, 400))); 用于根据玩家的朝向设置子弹的初始速度,使其沿玩家的朝向发射。

  5. 处理游戏手柄事件

    • button.index === 0 && value 判断A按钮是否按下,如果是则调用 this.shootBullet 方法发射子弹。
  6. 敌人被击中

    • bullet.setActive(false)bullet.setVisible(false) 使子弹失效并隐藏。

    • enemy.destroy() 销毁敌人对象。

案例4:实现鼠标和键盘组合输入

4.1 游戏目标

实现一个支持鼠标和键盘组合输入的游戏,玩家可以通过键盘控制角色的移动,通过鼠标点击发射子弹,通过鼠标移动调整角色的朝向。

4.2 代码实现


// 引入Phaser引擎

import Phaser from 'phaser';



// 创建游戏配置

const config = {

    type: Phaser.AUTO,

    width: 800,

    height: 600,

    physics: {

        default: 'arcade',

        arcade: {

            gravity: { y: 0 },

            debug: false

        }

    },

    scene: {

        preload: preload,

        create: create,

        update: update

    }

};



// 创建游戏实例

const game = new Phaser.Game(config);



// 预加载资源

function preload() {

    this.load.image('player', 'assets/player.png');

    this.load.image('bullet', 'assets/bullet.png');

}



// 创建游戏场景

function create() {

    // 创建玩家

    this.player = this.physics.add.sprite(400, 500, 'player');

    this.player.setCollideWorldBounds(true);



    // 创建子弹组

    this.bullets = this.physics.add.group({

        key: 'bullet',

        maxSize: 10,

        runChildUpdate: true

    });



    // 初始化键盘输入

    this.cursors = this.input.keyboard.createCursorKeys();



    // 设置射击

    this.input.on('pointerdown', this.shootBullet, this);



    // 设置角色朝向

    this.input.on('pointermove', this.updatePlayerDirection, this);

}



// 更新游戏场景

function update(time, delta) {

    // 移动玩家

    this.player.setVelocity(0);

    if (this.cursors.left.isDown) {

        this.player.setVelocityX(-200);

    } else if (this.cursors.right.isDown) {

        this.player.setVelocityX(200);

    }

    if (this.cursors.up.isDown) {

        this.player.setVelocityY(-200);

    } else if (this.cursors.down.isDown) {

        this.player.setVelocityY(200);

    }



    // 更新子弹

    this.bullets.children.iterate(function (bullet) {

        if (bullet.active) {

            bullet.setVelocityY(-400);

        }

    });



    // 检测碰撞

    this.physics.add.collider(this.bullets, this.enemies, this.hitEnemy, null, this);

}



// 射击子弹

function shootBullet(pointer) {

    const bullet = this.bullets.get();

    if (bullet) {

        bullet.setActive(true);

        bullet.setVisible(true);

        bullet.setPosition(this.player.x, this.player.y);

        bullet.setVelocity(Phaser.Math.Normalize(Phaser.Math.Vector2.FromAngle(this.player.angle, 400)));

    }

}



// 更新角色朝向

function updatePlayerDirection(pointer) {

    const dx = pointer.x - this.player.x;

    const dy = pointer.y - this.player.y;

    this.player.angle = Phaser.Math.RAD_TO_DEG * Math.atan2(dy, dx);

}



// 敌人被击中

function hitEnemy(bullet, enemy) {

    bullet.setActive(false);

    bullet.setVisible(false);

    enemy.destroy();

}

4.3 代码解释

  1. 预加载资源

    • this.load.image 方法用于加载玩家和子弹的图像资源。
  2. 创建游戏场景

    • this.player 创建了一个玩家角色,使用 setCollideWorldBounds 方法确保玩家不会移出屏幕边界。

    • this.bullets 创建了子弹组,maxSize 设置了子弹组的最大大小,runChildUpdate 允许子对象在每一帧更新时运行更新函数。

    • this.cursors = this.input.keyboard.createCursorKeys(); 用于初始化键盘输入,包括上下左右键。

    • this.input.on('pointerdown', this.shootBullet, this); 用于监听鼠标点击事件,当点击屏幕时调用 this.shootBullet 方法。

    • this.input.on('pointermove', this.updatePlayerDirection, this); 用于监听鼠标移动事件,当鼠标移动时调用 this.updatePlayerDirection 方法。

  3. 更新游戏场景

    • this.player.setVelocity(0); 用于重置玩家的移动速度,确保在没有按键按下时玩家停止移动。

    • if (this.cursors.left.isDown) { this.player.setVelocityX(-200); } 判断左箭头键是否按下,如果是则设置玩家的水平速度为-200,使其向左移动。

    • else if (this.cursors.right.isDown) { this.player.setVelocityX(200); } 判断右箭头键是否按下,如果是则设置玩家的水平速度为200,使其向右移动。

    • if (this.cursors.up.isDown) { this.player.setVelocityY(-200); } 判断上箭头键是否按下,如果是则设置玩家的垂直速度为-200,使其向上移动。

    • else if (this.cursors.down.isDown) { this.player.setVelocityY(200); } 判断下箭头键是否按下,如果是则设置玩家的垂直速度为200,使其向下移动。

    • this.bullets.children.iterate 遍历子弹组中的每个子弹,设置其垂直速度使其向上飞行。

    • this.physics.add.collider 用于检测子弹和敌人之间的碰撞,当发生碰撞时调用 this.hitEnemy 方法。

  4. 射击子弹

    • this.bullets.get 从子弹组中获取一个未活跃的子弹,设置其状态为活跃并显示在屏幕上,位置为玩家的位置。

    • bullet.setVelocity(Phaser.Math.Normalize(Phaser.Math.Vector2.FromAngle(this.player.angle, 400))); 用于根据玩家的朝向设置子弹的初始速度,使其沿玩家的朝向发射。

  5. 更新角色朝向

    • const dx = pointer.x - this.player.x; 计算鼠标指针与玩家角色在水平方向上的差值。

    • const dy = pointer.y - this.player.y; 计算鼠标指针与玩家角色在垂直方向上的差值。

    • this.player.angle = Phaser.Math.RAD_TO_DEG * Math.atan2(dy, dx); 使用 Math.atan2 计算玩家角色与鼠标指针之间的角度,并将其转换为度数,设置玩家角色的朝向。

  6. 敌人被击中

    • bullet.setActive(false)bullet.setVisible(false) 使子弹失效并隐藏。

    • enemy.destroy() 销毁敌人对象。

案例5:实现更复杂的组合输入(续)

5.3 代码解释(续)

  1. 预加载资源

    • this.load.image 方法用于加载玩家和子弹的图像资源。
  2. 创建游戏场景

    • this.player 创建了一个玩家角色,使用 setCollideWorldBounds 方法确保玩家不会移出屏幕边界。

    • this.bullets 创建了子弹组,maxSize 设置了子弹组的最大大小,runChildUpdate 允许子对象在每一帧更新时运行更新函数。

    • this.cursors = this.input.keyboard.createCursorKeys(); 用于初始化键盘输入,包括上下左右键。

    • this.input.gamepad.once('connected', (pad) => { this.pad = pad; }); 用于监听手柄连接事件并初始化手柄。

    • this.input.on('pointerdown', this.shootBullet, this); 用于监听鼠标点击事件,当点击屏幕时调用 this.shootBullet 方法。

    • this.input.gamepad.on('down', this.handleGamepad, this); 用于监听手柄按钮按下事件,当按下A按钮时调用 this.shootBullet 方法。

    • this.input.on('pointermove', this.updatePlayerDirection, this); 用于监听鼠标移动事件,当鼠标移动时调用 this.updatePlayerDirection 方法。

  3. 更新游戏场景

    • this.player.setVelocity(0); 用于重置玩家的移动速度,确保在没有按键按下时玩家停止移动。

    • if (this.cursors.left.isDown || (this.pad && this.pad.axes[0].value < -0.5)) { this.player.setVelocityX(-200); } 判断左箭头键或手柄左摇杆是否向左偏移,如果是则设置玩家的水平速度为-200,使其向左移动。

    • else if (this.cursors.right.isDown || (this.pad && this.pad.axes[0].value > 0.5)) { this.player.setVelocityX(200); } 判断右箭头键或手柄左摇杆是否向右偏移,如果是则设置玩家的水平速度为200,使其向右移动。

    • if (this.cursors.up.isDown || (this.pad && this.pad.axes[1].value < -0.5)) { this.player.setVelocityY(-200); } 判断上箭头键或手柄左摇杆是否向上偏移,如果是则设置玩家的垂直速度为-200,使其向上移动。

    • else if (this.cursors.down.isDown || (this.pad && this.pad.axes[1].value > 0.5)) { this.player.setVelocityY(200); } 判断下箭头键或手柄左摇杆是否向下偏移,如果是则设置玩家的垂直速度为200,使其向下移动。

    • this.bullets.children.iterate 遍历子弹组中的每个子弹,设置其垂直速度使其向上飞行。

    • this.physics.add.collider 用于检测子弹和敌人之间的碰撞,当发生碰撞时调用 this.hitEnemy 方法。

  4. 射击子弹

    • this.bullets.get 从子弹组中获取一个未活跃的子弹,设置其状态为活跃并显示在屏幕上,位置为玩家的位置。

    • bullet.setVelocity(Phaser.Math.Normalize(Phaser.Math.Vector2.FromAngle(this.player.angle, 400))); 用于根据玩家的朝向设置子弹的初始速度,使其沿玩家的朝向发射。

  5. 更新角色朝向

    • const dx = pointer.x - this.player.x; 计算鼠标指针与玩家角色在水平方向上的差值。

    • const dy = pointer.y - this.player.y; 计算鼠标指针与玩家角色在垂直方向上的差值。

    • this.player.angle = Phaser.Math.RAD_TO_DEG * Math.atan2(dy, dx); 使用 Math.atan2 计算玩家角色与鼠标指针之间的角度,并将其转换为度数,设置玩家角色的朝向。

  6. 处理游戏手柄事件

    • button.index === 0 && value 判断A按钮是否按下,如果是则调用 this.shootBullet 方法发射子弹。
  7. 敌人被击中

    • bullet.setActive(false)bullet.setVisible(false) 使子弹失效并隐藏。

    • enemy.destroy() 销毁敌人对象。

通过这些案例,你已经掌握了在Phaser引擎中处理用户输入的多种方法,包括鼠标、键盘、游戏手柄以及多点触控。这些技术可以灵活组合,以实现更复杂和丰富的游戏交互体验。希望这些案例对你在开发游戏时有所帮助!

如果你有任何问题或需要进一步的解释,请随时提问!
在这里插入图片描述

你可能感兴趣的:(游戏开发2,交互,linux,运维,服务器,网络,性能优化)