您的目标是获取任意坐标(我将其称为“世界空间”)并将它们映射到“屏幕空间”(显示器上的像素)。最好的方法确实是使用scale();但是,在您的代码中,您使用了scale(2)(从世界空间映射到更大的世界空间),然后您使用width / 2, height / 2(通常位于您的屏幕空间,但由于您之前按 2 缩放,因此您的 width / 2 和 height / 2 将乘以 2)。
相反,您应该使用scale() 从世界空间映射到屏幕空间,并使用世界空间坐标绘制对象。示例:
// World space of 400 x 400, chosen arbitrarily
final float worldWidth = 400.0
, worldHeight = 400.0;
void draw() {
// Map the world space (of 400 x 400) to screen space
/* Another way of thinking about this:
A value on the X scale of 0 to 400 is divided by 400 into the scale of 0.0 to 1.0,
and then is multiplied by the actual width of the screen;
Whatever fraction of the world space's width it was at,
it's now at that same fraction of the screen space's width.
*/
scale(width/worldWidth, height/worldHeight);
// Convert mouse coordinates from screen space to world space
/* Explanation:
We need to convert mouse coordinates from screen space to world space
if we want to use their values in world space (scale only affects drawing).
mouseX and mouseY are only changed when the mouse is moved;
If we converted on frames where they haven't been updated,
the conversions would accumulate.
pmouseX and pmouseY are set to mouseX and mouseY between draw() calls.
*/
if (pmouseX != mouseX || pmouseY != mouseY) {
mouseX = round(mouseX * worldWidth / width);
mouseY = round(mouseY * worldHeight / height);
}
// Example drawing code:
background(64);
// Same as ellipse(width/2, height/2, width/16, height/16) when not scaling
ellipse(200, 200, 25, 25);
// Same as ellipse(mouseX, mouseY, width/16, height/16) when not scaling
ellipse(mouseX, mouseY, 25, 25);
}
如果你想修正屏幕比例,这样当你画一个宽度和高度相等的东西时,无论你的屏幕比例是多少,它都会变成一个正方形,你可以这样做:
// World space of 1600 x 900 (16:9), chosen arbitrarily
final float worldWidth = 1600.0
, worldHeight = 900.0;
void draw() {
// Uniformly scale the world space so that it just fits the screen
float toScreenScale = min(width/worldWidth, height/worldHeight);
// Or: Uniformly scale the world space so that the screen just fits inside it
// float toScreenScale = max(width/worldWidth, height/worldHeight);
// Draw in the middle of the borders (when using min for toScreenScale)
float xBorder = (width - worldWidth * toScreenScale) / 2.0;
float yBorder = (height - worldHeight * toScreenScale) / 2.0;
translate(xBorder, yBorder);
// Scale world space uniformly
scale(toScreenScale);
// Convert mouse coordinates from screen space to world space
if (pmouseX != mouseX || pmouseY != mouseY) {
mouseX = round( (mouseX - xBorder) / toScreenScale );
mouseY = round( (mouseY - yBorder) / toScreenScale );
}
// Example drawing code:
background(64);
stroke(0);
fill(255);
ellipse(800, 450, 56.25, 56.25);
ellipse(mouseX, mouseY, 56.25, 56.25);
// Draw border to avoid spill-out (when using min for toScreenScale)
noStroke();
fill(0);
resetMatrix();
// Top
rect(0, 0, width, yBorder);
// Bottom
rect(0, height, width, -yBorder);
// Left
rect(0, 0, xBorder, height);
// Right
rect(width, 0, -xBorder, height);
}
如果您的世界空间和屏幕空间的比例不同,这将为您提供边框。如果您不手动填充这些边框(使用rect(),在您绘制完其他所有内容之后),可能会溢出到边框中。如果您将max 用于toScreenScale,它将切断而不是边界。
注意事项:
- 当我们将
mouseX或mouseY缩放到大于屏幕空间的世界空间时,舍入会使鼠标坐标不准确;相反,您最好制作一对新的float 坐标(或PVector),但您需要用该新变量替换代码中所有出现的mouseX 和mouseY。
没有愚蠢的问题