I'm trying to scale the size of a sprite in p5.js up a bit (factor of 2) and they look blurry when rendered. Obviously scaling up is usually not a great idea, however I've had success in making a pixelated sprite look crisp in raw JavaScript (based on this article: https://nluqo.github.io/broughlike-tutorial/stage1.html).
In JS I'd do something like this:
let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
ctx.imageSmoothingEnabled = false;
and drawing like this:
let tileSize = 32;
ctx.drawImage(
spritesheet,
sprite*16,
0,
16,
16,
x*tileSize,
y*tileSize,
tileSize,
tileSize
);
and when scaling sprites upwards, I get a nice clean effect (similar to how it is shown in the article I linked above).
Now I'm trying to port some code over to P5.js for demonstration purposes and have been trying to replicate the above upscaling (spritesheet is 16x16, would like to render as 32x32) and have been trying to replicate the typical ctx
calls, however they don't seem to work the same. Also of note is that I have tried to grab the canvas element from createCanvas
and get a 2D context, but the method doesn't exist.
Here is what I've tried so far:
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);
Additionally, I added this in my style.css
to no effect:
canvas {
display: block;
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-crisp-edges;
image-rendering: pixelated;
image-rendering: crisp-edges;
}
While the noSmooth()
function does affect images drawn with the image()
function, it does not affect the behavior of the copy()
function.
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>