正确缩放 Javascript Canvas 游戏

2024-05-10

我正在尝试根据屏幕尺寸动态缩放画布游戏。我了解如何根据屏幕尺寸调整画布大小,但我也想调整内容大小。基本上我希望游戏在每台设备上看起来都一样。我目前遇到的问题是,当拥有 4k 屏幕的人玩游戏时,他们可以轻松看到整个地图。当有人的屏幕非常小时,他们几乎看不到任何东西。有没有一种简单有效的方法来做到这一点?我尝试执行以下操作:

var maxWidth = 1920;
var maxHeight = 1080;

...

function resize() {
    c.width = screenWidth = window.innerWidth;
    c.height = screenHeight = window.innerHeight;
    widthToHeight = screenWidth / screenHeight; // ASPECT RATIO

    var scalerAmnt = (maxWidth + maxHeight )
            / (screenWidth + screenHeight);
    context.scale(scalerAmnt, scalerAmnt); 
}

如果我像这样缩放画布,则会产生不良结果。它偏离了中心,而且太大了。正如你所看到的,我设置了最大宽度和高度。基本上,我试图让游戏在每台设备上看起来与在具有该分辨率的机器上看起来相同。

现场演示:www.vertix.io

UPDATE: Here is an Image of what it currently looks like: enter image description here


您将面临一些问题。

如果不设置,高分辨率显示器将显示模糊ctx.imageSmoothingEnabled = false如果不设置,低分辨率显示器将显示锯齿效果ctx.imageSmoothingEnabled = true.

最好是不要超过最大分辨率。这是任意的,我的选择是使用大多数人使用的屏幕分辨率。一个例子屏幕统计 http://www.rapidtables.com/web/dev/screen-resolution-statistics.htm有许多网站提供此信息。选择最接近您的人口统计目标的一项。

对于大于此尺寸的显示器,不要增加分辨率,只需增加 DOM 元素的大小。

canvas.width and canvas.height设置画布的大小。canvas.style.width and canvas.style.height设置分辨率。

对于分辨率较低的显示器,请降低画布分辨率以适应屏幕分辨率。为设备提供额外的像素来渲染那些看不到的像素是没有意义的。当图像加载时,我亲自重新渲染所有图形以纠正较低分辨率显示的分辨率。同样,这是为了阻止设备渲染超出需要的像素(移动设备无法处理太多),并且平滑方法还有很多不足之处(即它是完全错误的)请观看此视频以解释原因电脑颜色坏了 https://youtu.be/LKnqECcg6Gw

小心降低分辨率。如果你有一张 100×100 像素的图像并且需要将其缩小到 93×93,那么它看起来不太好。仔细选择每个渲染元素的图形尺寸,以尽可能减少您将要显示的最常见的分辨率集。

还允许运动场尺寸有一些回旋余地,它们不必全部具有完全相同的尺寸。

更好的方法是将图形存储为基于矢量的图像(例如 SVG 或直接矢量渲染到画布的自定义格式),然后在加载时在设备上以正确的分辨率渲染图像。

这样你就剩下了这个方面。您对此无能为力,并且某些屏幕会比其他屏幕显示更多的游戏场地。您必须确定可以在宽度和高度上进行游戏的最小尺寸的游戏场地,并确保它不会低于该尺寸。

但尽管如此,大部分工作已经完成,您无法返回并重做所有工作,因此这里是简单的解决方案。

var nativeWidth = 1024;  // the resolution the games is designed to look best in
var nativeHeight = 768;

// the resolution of the device that is being used to play
var deviceWidth = window.innerWidth;  // please check for browser compatibility
var deviceHeight = window.innerHeight;

您有两个缩放选项。缩放以适合,或缩放以填充。

// A: This will ensure that the scale fills the device but will crop
// some of the top and bottom, or left and right of the play field.
// use the max scale.
var scaleFillNative = Math.max(deviceWidth / nativeWidth, deviceHeight / nativeHeight);

// B: this will ensure that all screens will see all of the native playscreen size
// but some displays will have extra playfield on the sides or top and bottom.
// use the min scale
var scaleFitNative = Math.min(deviceWidth / nativeWidth, deviceHeight / nativeHeight);

将画布分辨率和大小设置为

canvas.style.width = deviceWidth + "px";
canvas.style.height = deviceHeight + "px";
canvas.width = deviceWidth;
canvas.height = deviceHeight;

现在您需要设置渲染比例

// ctx is the canvas 2d context 
ctx.setTransform(
    scaleFitNative,0, // or use scaleFillNative 
    0,scaleFitNative,
    Math.floor(deviceWidth/2),
    Math.floor(deviceHeight/2)
);

这已将屏幕中心设置为原点。

UPDATE

我原来的答案有错误。

要获取本地资源左上角的偏移量,请执行以下操作:

var offSetToNativeTop = -nativeHeight/2; // incorrect
var offSetToNativeleft = -nativeWidth/2; // incorrect

应该...

var offSetToNativeTop = (-nativeHeight/2)*scaleFitNative; // correct
var offSetToNativeleft = (-nativeWidth/2)*scaleFitNative; // correct

or

var offSetToNativeTop = (-nativeHeight/2)*scaleFillNative; // correct
var offSetToNativeleft = (-nativeWidth/2)*scaleFillNative; // correct

对于由此造成的任何不便,我们深表歉意。

获取设备左上角的偏移量

var offsetDeviceTop = -(deviceHeight/scaleFitNative)/2;
var offsetDeviceLeft = -(deviceWidth/scaleFitNative)/2;

获取设备场地显示尺寸

var deviceDisplayWidth = deviceWidth/scaleFitNative;
var deviceDisplayHeight = deviceHeight/scaleFitNative;

不要忘记平滑。

if(scaleFitNative < 1){
    ctx.imageSmoothingEnabled = true; // turn it on for low res screens
}else{
    ctx.imageSmoothingEnabled = false; // turn it off for high res screens.
}

您还可以对单个渲染项目执行此操作,具体取决于其比例和您个人的偏好,即它们看起来如何平滑、缩小、平滑扩展或不平滑大小。

这应该为您提供为所有设备渲染图形所需的一切

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

正确缩放 Javascript Canvas 游戏 的相关文章

随机推荐

  • 通过 org.springframework.orm.hibernate4.LocalSessionFactoryBean 创建 HibernateTemplate

    我使用 Spring 3 1 Hibernate 4 我创建了以下内容sessionFactory
  • 在类之间调度事件

    我有一个自定义事件类 public class FFTDrawEvent extends Event public static const DRAW EVENT String drawEvent private var param Arr
  • MPMoviePlayerController 的工具栏上有一个自定义按钮

    您可能在 iPhone 中通过 YouTube 观看过视频 普通 MPMoviePlayerController 有上一个 下一个和播放 暂停按钮 Youtube 播放器上有两个额外的按钮 gt 添加到左侧的收藏夹 gt 通过电子邮件发送右
  • Gradle 5 JUnit BOM 和 Spring Boot 版本不正确

    我正在使用 Gradle 5 的 BOM 物料清单 feature https docs gradle org 5 0 userguide managing transitive dependencies html sec bom impo
  • 从流中读取 PNG 文件

    我试图为 android mobile so 在服务器端构建 RDP 应用程序 我使用机器人类发送 png 图像 但在客户端我无法读取该消息并将其打印在我的 android 设备上 我正在使用以下代码来读取 JPEG 文件正文数据 并且我能
  • 在 Python 2.6 中访问外部作用域

    比如说 我有一些带有变量的作用域 并且在此作用域中调用的函数想要更改一些不可变变量 def outer s qwerty n 123 modify def modify s abcd n 456 是否有可能以某种方式访问 外部范围 就像是n
  • perl xs - 从 c 数组返回 perl 数组

    使用 XS 我尝试将值从 C 数组传递到可在脚本中使用的 Perl 数组 这是我的 xs 文件中的代码 AV DoubleArray getPerlArray CODE r newAV for size t i 0 i lt THIS gt
  • 如何使用 JSON 结果更新 Extjs 进度条?

    我在让进度条从 Json 结果中检索进度并根据每 10 秒的计时器检查更新进度条时遇到一些困难 我可以创建这样的 json 结果 success true progress 0 2 我想总体思路是 我需要一个间隔设置为 10 秒的任务 并让
  • 既然 Gradle 和 Maven 都弃用了 http,如何使用 Liferay Mobile SDK 6.2.18 生成 jar 库?

    在我当前的项目中 我们正在维护 开发使用客户网站 liferay 6 2 服务的移动 android iOS 应用程序 每当后端的人员生成新服务 或者只是将现有服务更新为具有新功能的新版本 时 我们需要使用 Liferay Mobile S
  • 如何从本地系统将 lxml 安装到 virtualenv 中?

    我的系统上安装了 lxml 模块 debian 包python lxml 对于python 2 6 我也使用基于python2 6的virtualenv 使用标志安装 no site packages 是否可以在虚拟环境中安装 lxml 而
  • 哈德森中的java OutOfMemoryError

    我在 hudson 中运行 pmd findbugs 时收到以下错误 FATAL Java heap space java lang OutOfMemoryError Java heap space at java util HashMap
  • 使用 linq 组合对象

    我有一个类的 2 个实例 它实现了IEnumerable界面 我想创建一个新对象并将它们合并为一个 我明白我可以使用for each去做这个 有 linq lambda 表达式的方法可以做到这一点吗 EDIT public class Me
  • 2.5 是否有一个 Python 模块提供类似于 2.6 中的 "string".format() 调用的功能?

    2 5 是否有免费的 Python 模块提供类似于 2 6 3 x 中的 string format 调用的功能 我正在为 2 5 编写新代码 我不想在新代码中使用 格式表达式 您可能会发现这里的代码可以适应您的需要 http svn py
  • SlidingTabLayout 中自定义未选择的选项卡文本颜色

    我正在使用SlidingTabLayout类来在我的 Android 应用程序中显示选项卡 我正在使用我设置的自定义选项卡视图setCustomTabView功能 虽然我可以轻松自定义选定选项卡的文本颜色 但我找不到自定义未选定选项卡的文本
  • 如何取消 Postgres 中的错误命令(从终端)?

    我在尝试编写函数时写了一个错误的命令 我在函数中犯了一个错误 并且想在没有完成函数的情况下退出它 并且我想退出它 但是终端的命令提示符不允许我退出 我试过这个 https unix stackexchange com questions 4
  • 如何为我的杆和楔子添加纹理?

    我正在使用绘制几个条形图和饼图matplotlib pyplot bar http matplotlib org api pyplot api html matplotlib pyplot bar and matplotlib pyplot
  • PSD 到 html 转换 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • WSGI 中的 httplib CannotSendRequest 错误

    我使用了两个不同的 python oauth 库和 Django 来通过 twitter 进行身份验证 该设置是在带有 WSGI 的 apache 上进行的 当我重新启动服务器时 大约 10 分钟一切正常 然后 httplib 似乎锁定了
  • 如何创建 Keras 层来执行 4D 卷积 (Conv4D)?

    看起来tf nn convolution应该能够进行 4D 卷积 但我无法成功创建 Keras 层来使用此函数 我尝试过使用 KerasLambda层来包裹tf nn convolution功能 但也许其他人有更好的主意 我想利用数据的高维
  • 正确缩放 Javascript Canvas 游戏

    我正在尝试根据屏幕尺寸动态缩放画布游戏 我了解如何根据屏幕尺寸调整画布大小 但我也想调整内容大小 基本上我希望游戏在每台设备上看起来都一样 我目前遇到的问题是 当拥有 4k 屏幕的人玩游戏时 他们可以轻松看到整个地图 当有人的屏幕非常小时