在 p5.js 中放大时的模糊精灵

Blurry sprites when scaled up in p5.js

我正在尝试将 p5.js 中的精灵的大小放大一点(2 倍),但它们在渲染时看起来很模糊。显然放大通常不是一个好主意,但是我已经成功地使像素化精灵在原始 JavaScript 中看起来清晰(基于这篇文章:https://nluqo.github.io/broughlike-tutorial/stage1.html)。

在 JS 中我会这样做:

let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
ctx.imageSmoothingEnabled = false;

画成这样:

let tileSize = 32;
ctx.drawImage(
  spritesheet,
  sprite*16,
  0,
  16,
  16,
  x*tileSize,
  y*tileSize,
  tileSize,
  tileSize
);

当向上缩放精灵时,我得到了一个很好的干净效果(类似于我上面链接的文章中显示的效果)。

现在我正尝试将一些代码移植到 P5.js 以用于演示目的,并且一直在尝试复制上述放大(spritesheet 是 16x16,想呈现为 32x32)并且已经 尝试 复制典型的 ctx 调用,但它们的工作方式似乎不同。另外值得注意的是,我试图从 createCanvas 中获取 canvas 元素并获取 2D 上下文,但该方法不存在。

这是我目前尝试过的方法:

createCanvas(1024, 800);
noSmooth();
...
const spriteSize = 16;
const spriteScaled = 32;

let _c = 0; // col lookup into spritesheet
let _r = 0; // row lookup into spritesheet
test_image = createImage(spriteScaled, spriteScaled);
test_image.copy(
  tileMap,
  _c * spriteSize,
  _r * spriteSize,
  spriteSize,
  spriteSize,
  0,
  0,
  spriteScaled,
  spriteScaled
);
// also tried this:
// test_image.resize(spriteScaled, 0);

此外,我在 style.css 中添加了这个但没有效果:

canvas {
  display: block;
  image-rendering: -moz-crisp-edges;
  image-rendering: -webkit-crisp-edges;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

虽然 noSmooth() 函数会影响使用 image() 函数绘制的图像,但它不会影响 copy() 函数的行为。

let imgUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAAh0lEQVQ4y92TMQ6AIAxFX40bB3HyIE4ex00jm+dj8iDOdRGDWhMim39seeWT8gVbatSEjKIC6DY+DzpvMnUKR3AN/mnp6Inzmg6RFLbAu5p2jG4EoIqNHNhSBegy5QNr8PE5enHwVT8YcK5xmaDv+L7GUgek63xzcr/9NQvWvxhmOz9SmsZi7UmSK41htVcqAAAAAElFTkSuQmCC";

const spriteSize = 16;
const spriteScaled = 32;

let tileMap;
let test_image;

function preload() {
  tileMap = loadImage(imgUrl);
}

function setup() {
  createCanvas(1024, 800);
  noSmooth();

  let _c = 0; // col lookup into spritesheet
  let _r = 0; // row lookup into spritesheet
  test_image = createImage(spriteSize, spriteSize);
  // Don't resize when copying. This will cause interpolation to happen.
  test_image.copy(
    tileMap,
    _c * spriteSize,
    _r * spriteSize,
    spriteSize,
    spriteSize,
    0,
    0,
    spriteSize,
    spriteSize
  );
}

function draw() {
  // Only resize when you actually draw the sprite
  image(test_image, 0, 0, spriteScaled, spriteScaled);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>