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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 16:12:35