You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:Phaser 3迷宫游戏像素完美碰撞实现方案及示例

Phaser 3 迷宫像素完美碰撞实现方案

直接上可运行的实现代码,适配你用单张迷宫墙体精灵的需求:

核心实现逻辑

用静态精灵承载整张迷宫墙体图,通过Phaser Arcade物理引擎的像素碰撞检测API,让玩家与墙体的不透明像素发生碰撞,透明区域可通行。

1. 资源要求

  • 迷宫墙体图:墙体部分为不透明像素(比如纯黑),可走区域完全透明,保存为PNG格式
  • 玩家精灵:任意带透明背景的精灵图或精灵表

2. 完整代码示例

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 0 },
            debug: false // 调试时设为true,可查看碰撞体边界
        }
    },
    scene: {
        preload: preload,
        create: create,
        update: update
    }
};

new Phaser.Game(config);

function preload() {
    // 替换为你的资源路径
    this.load.image('maze', 'assets/maze_walls.png');
    this.load.spritesheet('player', 'assets/player_sprite.png', { frameWidth: 32, frameHeight: 32 });
}

function create() {
    // 创建迷宫静态精灵,居中放置(根据你的迷宫尺寸调整坐标)
    const maze = this.physics.add.staticSprite(400, 300, 'maze');
    // 开启四个方向的碰撞检测
    maze.body.checkCollision.up = true;
    maze.body.checkCollision.down = true;
    maze.body.checkCollision.left = true;
    maze.body.checkCollision.right = true;

    // 创建玩家动态精灵,初始位置设为迷宫入口
    const player = this.physics.add.sprite(60, 60, 'player');
    player.setCollideWorldBounds(true); // 限制玩家不出屏幕

    // 绑定碰撞:关键是启用像素完美检测
    this.physics.add.collider(player, maze, null, pixelPerfectCheck, this);

    // 键盘控制
    this.cursors = this.input.keyboard.createCursorKeys();
}

function update() {
    // 玩家移动逻辑
    this.player.setVelocity(0);
    if (this.cursors.left.isDown) {
        this.player.setVelocityX(-180);
    } else if (this.cursors.right.isDown) {
        this.player.setVelocityX(180);
    }
    if (this.cursors.up.isDown) {
        this.player.setVelocityY(-180);
    } else if (this.cursors.down.isDown) {
        this.player.setVelocityY(180);
    }
}

// 自定义像素完美碰撞检测函数
function pixelPerfectCheck(player, maze) {
    const playerFrame = player.frame;
    const mazeFrame = maze.frame;

    // 计算两个精灵的重叠区域
    const playerBounds = player.getBounds();
    const mazeBounds = maze.getBounds();
    const overlap = Phaser.Geom.Rectangle.Intersection(playerBounds, mazeBounds);

    // 如果没有重叠,直接返回false
    if (overlap.width <= 0 || overlap.height <= 0) return false;

    // 遍历重叠区域的每个像素
    for (let x = overlap.x; x < overlap.x + overlap.width; x++) {
        for (let y = overlap.y; y < overlap.y + overlap.height; y++) {
            // 转换为精灵本地坐标
            const playerX = Math.floor(x - playerBounds.x);
            const playerY = Math.floor(y - playerBounds.y);
            const mazeX = Math.floor(x - mazeBounds.x);
            const mazeY = Math.floor(y - mazeBounds.y);

            // 获取像素透明度
            const playerAlpha = playerFrame.texture.getPixelAlpha(playerX, playerY, playerFrame.cutX, playerFrame.cutY);
            const mazeAlpha = mazeFrame.texture.getPixelAlpha(mazeX, mazeY, mazeFrame.cutX, mazeFrame.cutY);

            // 只要有一对不透明像素重叠,就判定碰撞
            if (playerAlpha > 0 && mazeAlpha > 0) {
                return true;
            }
        }
    }
    return false;
}

关键注意点

  • 精灵原点:默认是中心(0.5),如果你的迷宫图是左上角对齐,记得设置maze.setOrigin(0, 0)并调整坐标
  • 性能优化:如果迷宫很大,不要逐像素检测,可以每隔2-3个像素采样一次,减少计算量
  • 调试技巧:开启physics.arcade.debug = true,能看到物理体的矩形边界,方便排查位置偏移问题
  • 精灵表适配:如果玩家用的是精灵表,player.frame会自动获取当前帧的像素数据,无需额外处理

内容的提问来源于stack exchange,提问作者EmptyStone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 15:20:33