使用p5.js开发瞄准训练器时图片目标无法点击及TypeError错误排查求助
解决p5.js瞄准训练器的图片点击失效与
TypeError: img2 is not a function问题 看起来你在开发瞄准训练器时遇到了两个核心问题:图片目标无法点击,以及img2 is not a function的错误。我来一步步帮你解决:
一、先修复TypeError: img2 is not a function错误
这个错误主要来自两个可能的原因:
1. 未闭合的代码块
你的代码末尾没有闭合if (MENU == 1)的代码块和draw()函数,这会导致JavaScript解析器误读代码,把img2识别为函数调用。请在代码最后补上两个闭合大括号:
} // 闭合if (keyIsDown(27)) } // 闭合if (MENU == 1) } // 闭合draw()函数
2. 图片加载失败
如果durtburd.png的路径不正确,loadImage会返回undefined,后续调用image(img2, x, y)时会引发错误。可以在draw里先检查图片是否加载完成:
if (img2) { // 确保图片加载完成再显示 image(img2, x - targetSize/2, y - targetSize/2, targetSize, targetSize); }
二、解决图片目标无法点击的问题
点击失效的根源是状态判断缺失和点击区域不匹配,我们逐一修复:
1. 只在游戏状态处理点击
你的mousePressed函数没有判断当前是否处于游戏状态(MENU == 1),导致菜单页面的点击也会触发目标判断。先加上状态过滤:
function mousePressed() { if (MENU !== 1) return; // 非游戏状态直接返回,不处理点击 // 后续点击判断代码 }
2. 适配图片的点击区域判断
原来的dist判断是针对椭圆的,但图片是矩形区域,而且image默认以左上角为原点,和椭圆的中心原点不同。我们需要调整坐标并判断鼠标是否在图片范围内:
首先定义目标尺寸(比如和原来的椭圆一致):
const radius = 20; const targetSize = radius * 2; // 图片显示的宽高
然后在mousePressed里判断:
// 计算图片的左上角坐标(让图片中心和椭圆中心重合) let imgLeft = x - targetSize/2; let imgTop = y - targetSize/2; // 判断鼠标是否在图片矩形内 if (mouseX > imgLeft && mouseX < imgLeft + targetSize && mouseY > imgTop && mouseY < imgTop + targetSize) { newCircle(); score++; } else { // 可以在这里处理点击空的情况,比如减少生命值 shootFail++; life = Math.max(0, life - 1); }
同时,在draw里显示图片时,也要调整坐标让它和椭圆位置一致:
image(img2, x - targetSize/2, y - targetSize/2, targetSize, targetSize);
3. 修正定时器的位置
你把setInterval(newCircle, 1000);放在了setup外面,这可能导致页面加载时就触发定时器,而此时x和y还未初始化。请把它移到setup函数里,同时初始化第一个目标位置:
function setup() { createCanvas(800, 600); newCircle(); // 初始化第一个目标 setInterval(newCircle, 1000); // 启动定时器 }
三、完整修正后的核心代码片段
let MENU = 0; let img; let img2; var life = 3; var score = 0; var shootFail = 0; var x, y; const radius = 20; const targetSize = radius * 2; // 统一目标尺寸 function preload() { img = loadImage('GAME_logo.png'); img2 = loadImage('durtburd.png'); } function setup() { createCanvas(800, 600); newCircle(); // 初始化第一个目标 setInterval(newCircle, 1000); } function mousePressed() { if (MENU !== 1) return; // 非游戏状态不处理点击 // 判断鼠标是否在图片目标内 let imgLeft = x - targetSize/2; let imgTop = y - targetSize/2; if (mouseX > imgLeft && mouseX < imgLeft + targetSize && mouseY > imgTop && mouseY < imgTop + targetSize) { newCircle(); score++; } else { // 处理空点击 shootFail++; life = Math.max(0, life - 1); } } function newCircle() { x = random(targetSize/2, width - targetSize/2); // 避免目标超出画布 y = random(targetSize/2, height - targetSize/2); } function draw() { cursor('test2.cur'); background(225); // 菜单页面 if (MENU == 0) { // 绘制菜单按钮 fill('darkgray'); rect(50, 50, 200, 75); rect(50, 200, 200, 75); rect(50, 350, 200, 75); // 绘制菜单文字 textSize(25); fill('white'); text('START', 60, 90); text('REFLEX', 60, 110); textSize(24); text('INSTRUCTIONS', 60, 250); textSize(25); text('START', 60, 390); text('TRACKING', 60, 410); scale(0.9); image(img, 320, 50, 530, 520); } // 游戏页面 if (MENU == 1) { noStroke(); background(35, 39, 42); fill('white'); textSize(20); text('Press escape to return to MENU', 500, 30); textSize(60); fill('red'); text('♥'.repeat(life), 400, 300); fill('white'); textSize(30); text("Score: " + score, width/2, height/2 + 40); text("Misses: " + shootFail, width/2, height/2 + 65); // 显示图片目标(确保加载完成) if (img2) { image(img2, x - targetSize/2, y - targetSize/2, targetSize, targetSize); } if (keyIsDown(27)) { MENU = 0; } } }
额外提示
- 可以在
newCircle里限制目标的位置,避免超出画布范围(上面的代码已经做了) - 点击空的情况可以添加生命值减少的逻辑,让游戏更完整
内容的提问来源于stack exchange,提问作者decobra
相关产品推荐
相关产品推荐

