javascript 在p5.js中按下某个键后,如何使图像保留在屏幕上?

pn9klfpd  于 2022-12-25  发布在  Java
关注(0)|答案(1)|浏览(165)

我的p5.js项目遇到了一点问题。目前为止,每次我按向上键时,我的图片都会出现在屏幕上,但只有一秒钟。有没有办法让它们在按下向上键后仍然显示在屏幕上?我希望每次我按不同的箭头键时,都能在相同的位置弹出不同的图片集。并使最后一组图像消失。

function preload() {
  img1 = loadImage("img/Q.png");
  img2 = loadImage("img/W.png");
  img3 = loadImage("img/E.png");
  img4 = loadImage("img/R.png");
  img5 = loadImage("img/T.png");
  img6 = loadImage("img/Y.png");
  song1 = loadSound("audio/1.wav");
  song2 = loadSound("audio/2.wav");
  song3 = loadSound("audio/3.wav");
  song4 = loadSound("audio/4.wav");
  song5 = loadSound("audio/5.wav");
  song6 = loadSound("audio/6.wav");
}

function setup() {
  createCanvas(1024, 764);
  h = 0;
}

function draw() {
  background(0);
}

function keyTyped() {
  typed += key;
}

function keyPressed() {
  if (keyCode === UP_ARROW) {
    image(img1, 20, 650, 100, 100);
    image(img2, 200, 650, 100, 100);
    image(img3, 380, 650, 100, 100);
    image(img4, 560, 650, 100, 100);
    image(img5, 740, 650, 100, 100);
    image(img6, 910, 650, 100, 100);

    if (key == 'q' || key == 'Q') {
      image(img1, 20, 550, 100, 100);
    }
    if (key == 'w' || key == 'W') {
      image(img2, 200, 550, 100, 100);
    }
    if (key == 'e' || key == 'E') {
      image(img3, 380, 550, 100, 100);
    }
    if (key == 'r' || key == 'R') {
      image(img4, 560, 550, 100, 100);
    }
    if (key == 't' || key == 'T') {
      image(img5, 740, 550, 100, 100);
    }
    if (key == 'y' || key == 'Y') {
      image(img6, 910, 550, 100, 100);
    }
  }
  if (key == '2') {
    image(img1, 20, 650, 100, 100);
  }
}
eimct9ow

eimct9ow1#

图像消失的原因是因为draw()函数大约每秒被调用60次来支持动画,你的draw()的内容是典型的擦屏background(0),一般来说,在清除背景后,draw()的下一步是重新绘制应该出现在屏幕上的对象。
现在,keyPressed处理程序只在按下某个键时触发一次,所以如果它渲染一个图像,在它被稍后在draw()中运行的background(0)清除之前,您最多只能看到一瞬间的图像:

keyPressed()/image()
            |
            V
... draw() -> draw() -> draw() -> draw() -> ...
      |         |         |         |
      |         v         v         |
      +-------->background(0)<------+ // erases everything

time -->

有几种方法可以处理这种情况:
1.将绘制代码移到draw(),并在主循环中而不是在keyPressed处理程序中检查keyCode/key。这使您有机会在每次background(0)调用后绘制。直接在draw()中测试keyCode/key的缺点是,它不会" t适用于多个密钥,因为keykeyCode一次只能保存单个值。
1.在setup()中调用noLoop(),使draw()只触发一次,这样background(0)就不会向主机发送垃圾邮件。对于动画驱动的应用,这可能是错误的方法,但对于事件驱动的非动画情况,它可能很有用。例如,在本例中,你可以使用keyReleased()触发另一个调用background(0)来擦除屏幕。可以使用loop()noLoop(0)策略性地启用和禁用事件循环。
1.将上面的#1与multi-keypress handler结合起来,multi-keypress handler跟踪用户一次按下的所有键,然后在draw()函数中根据当前按下的键决定在每一帧上显示什么。
在这个特定的例子中,由于您希望处理多个键,因此基本上所有实现都需要多键处理程序,但是为了保持简单,我将从没有多键处理程序开始。
这里有一些通用的例子,你可以采用。注意,我使用的是对象和数组,而不是img1img2,...和if s,并且我调整了坐标,使其更容易在堆栈片段中看到。键始终是QWERTY的。可能有一个内容类型的头警告,你可以忽略--这可能是占位符API的问题。

示例1(draw()中的键检测,一次一个键):

x一个一个一个一个x一个一个二个x
由于key保存最后按下的任何键,因此即使在最后一个键被释放后,它也会保留与该键关联的图像。

示例2(noLoop()仅具有keyPressed):

一个三个三个一个
实施例3(具有keyPressedkeyReleasednoLoop()):

const keyMapping =  {
  q: {
    url: "http://placekitten.com/40/40",
    coords: [0, 0, 40, 40],
  },
  w: {
    url: "http://placekitten.com/40/60",
    coords: [40, 0, 40, 60],
  },
  e: {
    url: "http://placekitten.com/40/80",
    coords: [80, 0, 40, 80],
  },
  r: {
    url: "http://placekitten.com/40/100",
    coords: [120, 0, 40, 100],
  },
  t: {
    url: "http://placekitten.com/40/120",
    coords: [160, 0, 40, 120],
  },
  y: {
    url: "http://placekitten.com/40/140",
    coords: [200, 0, 40, 140],
  },
};

function preload() {
  for (const k in keyMapping) {
    keyMapping[k].image = loadImage(keyMapping[k].url);
  }
}

function setup() {
  createCanvas(240, 140);
  noLoop();
}

function draw() {
  background(0);
}

function keyPressed() {
  const toDraw = keyMapping[key];
  
  if (toDraw) {
    image(toDraw.image, ...toDraw.coords);
  }
}

function keyReleased() {
  if (!keyIsPressed) { // optional
    background(0);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>

请注意,operating system may limit how many keys can be pressed at once.

示例4(noLoop()keyPressedkeyReleased以及一组按键):
const pressed = new Set();
const keyMapping =  {
  q: {
    url: "http://placekitten.com/40/40",
    coords: [0, 0, 40, 40],
  },
  w: {
    url: "http://placekitten.com/40/60",
    coords: [40, 0, 40, 60],
  },
  e: {
    url: "http://placekitten.com/40/80",
    coords: [80, 0, 40, 80],
  },
  r: {
    url: "http://placekitten.com/40/100",
    coords: [120, 0, 40, 100],
  },
  t: {
    url: "http://placekitten.com/40/120",
    coords: [160, 0, 40, 120],
  },
  y: {
    url: "http://placekitten.com/40/140",
    coords: [200, 0, 40, 140],
  },
};

function preload() {
  for (const k in keyMapping) {
    keyMapping[k].image = loadImage(keyMapping[k].url);
  }
}

function setup() {
  createCanvas(240, 140);
  noLoop();
}

function draw() {
  background(0);
}

function keyPressed() {
  pressed.add(key);
  showImage(key);
}

function keyReleased() {
  pressed.delete(key);
  background(0);

  // optionally redraw images for keys still pressed
  for (const k of [...pressed]) {
    showImage(k);
  }
}

function showImage(k) {
  const toDraw = keyMapping[k];

  if (toDraw) {
    image(toDraw.image, ...toDraw.coords);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
示例5(draw()keyPressedkeyReleased以及一组按键):
const pressed = new Set();
const keyMapping =  {
  q: {
    url: "http://placekitten.com/40/40",
    coords: [0, 0, 40, 40],
  },
  w: {
    url: "http://placekitten.com/40/60",
    coords: [40, 0, 40, 60],
  },
  e: {
    url: "http://placekitten.com/40/80",
    coords: [80, 0, 40, 80],
  },
  r: {
    url: "http://placekitten.com/40/100",
    coords: [120, 0, 40, 100],
  },
  t: {
    url: "http://placekitten.com/40/120",
    coords: [160, 0, 40, 120],
  },
  y: {
    url: "http://placekitten.com/40/140",
    coords: [200, 0, 40, 140],
  },
};

function preload() {
  for (const k in keyMapping) {
    keyMapping[k].image = loadImage(keyMapping[k].url);
  }
}

function setup() {
  createCanvas(240, 140);
}

function draw() {
  background(0);
  
  for (const k of [...pressed]) {
    showImage(k);
  }
}

function keyPressed() {
  pressed.add(key);
}

function keyReleased() {
  pressed.delete(key);
}

function showImage(k) {
  const toDraw = keyMapping[k];

  if (toDraw) {
    image(toDraw.image, ...toDraw.coords);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
示例6(draw()keyPressedkeyReleased以及一组按下的键,并且需要按住向上箭头键以激活QWERTY键):

一个一个一个一个
这里唯一的修改是一个条件,以确保用户在绘制任何东西之前按住箭头键,希望实现OP的最初意图。

//         vvvvvvvvvvvvvvvvvvvvvvvvv
if (toDraw && pressed.has("ArrowUp")) {
  image(toDraw.image, ...toDraw.coords);
}

相关问题