如何在JavaScript中检测鼠标指针所在颜色以重置迷宫游戏?
光标迷宫游戏:鼠标触壁检测方案解析
核心问题结论
通过颜色识别检测鼠标是否触碰墙壁的方案不可行。浏览器没有原生API支持直接检测鼠标所在位置的画布像素颜色,onmouseover事件仅能作用于DOM元素,无法识别Canvas绘制的像素内容。
最优替代方案:利用迷宫数据结构检测
你已经通过maze.tiles维护了完整的迷宫墙信息,直接基于鼠标坐标和这些数据进行碰撞检测才是高效且可靠的方案,不需要额外的颜色识别逻辑。具体实现步骤如下:
- 将鼠标坐标转换为迷宫的网格坐标(每个tile尺寸为
res=50) - 根据网格坐标定位到对应的tile,判断鼠标是否处于墙壁区域
- 若检测到触碰墙壁,触发游戏重置逻辑
修改后的完整代码
let maze = null; let res = 50; let mazeSizes = [25,50]; let gameActive = true; // 标记游戏是否在运行 function setup() { createCanvas(800, 450); noStroke(); makeMaze(width/res + 2, height/res + 2); drawMaze(); } let count = 0; function draw() { if (!gameActive) return; // 游戏重置后暂停绘制 fill("#39A7FF"); ellipse(775, 425, 20, 20); // 生成迷宫的逻辑 if(count % 10 == 0) { // 调整计数步长,避免过度刷新 if(maze.stack.length != 0) { background("#68c7ff"); mazeIterate(); drawMaze(); } } count++; // 检测鼠标是否触碰墙壁 checkMouseCollision(); } // 鼠标碰撞检测函数 function checkMouseCollision() { // 转换鼠标坐标为迷宫网格坐标(考虑translate的偏移) let gridX = floor((mouseX + res) / res); let gridY = floor((mouseY + res) / res); // 确保坐标在迷宫范围内 if(gridX < 0 || gridX >= maze.w || gridY < 0 || gridY >= maze.h) { resetGame(); return; } let tile = maze.tiles[gridX][gridY]; // 计算鼠标在tile内的相对位置 let relX = (mouseX + res) % res; let relY = (mouseY + res) % res; // 检测是否触碰当前tile的墙壁(匹配墙壁线宽2px) if(tile.up === "wall" && relY < 2) { resetGame(); } if(tile.down === "wall" && relY > res - 2) { resetGame(); } if(tile.left === "wall" && relX > res - 2) { resetGame(); } if(tile.right === "wall" && relX < 2) { resetGame(); } } // 游戏重置函数 function resetGame() { gameActive = false; setTimeout(() => { background("#68c7ff"); makeMaze(width/res + 2, height/res + 2); gameActive = true; count = 0; }, 500); // 短暂延迟后重置 } function makeMaze(w, h) { maze = { "stack":[], "tiles":[], "w":w, "h":h }; for(let i = 0; i < w; i++) { maze.tiles[i] = []; for(let j = 0; j < h; j++) { maze.tiles[i][j] = { "up":"wall", "down":"wall", "left":"wall", "right":"wall", "isStart":false, "isCurrent":false, "x":i, "y":j, "seen":false } if(i == 0 || i == w-1 || j == 0 || j == h-1) { maze.tiles[i][j].seen = true; } } } maze.tiles[1][1].isCurrent = true; maze.tiles[1][1].isStart = true; maze.tiles[1][1].seen = true; maze.stack.push(maze.tiles[1][1]); } function mazeIterate() { let current = maze.stack.pop(); let tileAndWall = pickNeighbor(current); if(tileAndWall) { maze.stack.push(current); tileAndWall.tile[tileAndWall.wall] = "open"; current[opositeWall( tileAndWall.wall)] = "open"; tileAndWall.tile.seen = true; maze.stack.push(tileAndWall.tile); current.isCurrent = false; tileAndWall.tile.isCurrent = true; } else if(maze.stack.length != 0) { current.isCurrent = false; maze.stack[ maze.stack.length-1].isCurrent = true; } } function pickNeighbor(tile) { let unSeen = []; let upTile = maze.tiles[tile.x][tile.y+1]; if(!upTile.seen) { unSeen.push({ "tile":upTile, "wall":"up" }); } let downTile = maze.tiles[tile.x][tile.y-1]; if(!downTile.seen) { unSeen.push({ "tile":downTile, "wall":"down" }); } let rightTile = maze.tiles[tile.x+1][tile.y]; if(!rightTile.seen) { unSeen.push({ "tile":rightTile, "wall":"right" }); } let leftTile = maze.tiles[tile.x-1][tile.y]; if(!leftTile.seen) { unSeen.push({ "tile":leftTile, "wall":"left" }); } if(unSeen.length == 0) { return null; } return unSeen[Math.floor( Math.random()*unSeen.length )]; } function opositeWall(wall) { if(wall == "up") { return "down" } else if(wall == "down") { return "up" } else if(wall == "right") { return "left" } else if(wall == "left") { return "right" } return -1; } function drawMaze() { push(); translate(-res, -res); for(let i = 0; i < maze.tiles.length; i++) { for(let j = 0; j < maze.tiles[i].length; j++) { let tile = maze.tiles[i][j]; drawTile(tile, i, j); } } pop(); } function drawTile(tile, i, j) { strokeWeight(0); if(tile.seen == true) { fill("#24698e"); square(i*res, j*res, res); strokeWeight(2); stroke("#c4ecff"); if(tile.up == "wall") { line((i)*res, (j)*res, (i+1)*res, (j)*res); } if(tile.down == "wall") { line((i)*res, (j+1)*res, (i+1)*res, (j+1)*res); } if(tile.left == "wall") { line((i+1)*res, (j)*res, (i+1)*res, (j+1)*res); } if(tile.right == "wall") { line((i)*res, (j)*res, (i)*res, (j+1)*res); } } if(tile.isCurrent) { fill("#00faff") noStroke(); circle(i*res + res/2, j*res + res/2, res/3); } }
代码说明
- 添加
gameActive变量控制游戏状态,重置时暂停绘制流程 checkMouseCollision函数将鼠标坐标转换为网格坐标,通过tile的wall属性精准判断是否触碰墙壁(匹配绘制时的2px线宽)resetGame函数实现游戏重置逻辑,延迟0.5秒后重新生成迷宫,提升用户体验
内容的提问来源于stack exchange,提问作者Sdwhit17
相关产品推荐
相关产品推荐

