求助: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
相关产品推荐
相关产品推荐

