2015-11-04 139 views
2

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

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: 这里是什么它目前看起来像一个图片: enter image description here

+0

你能添加截图吗? –

+0

我添加了一个链接到正在运行的演示。所以你可以看到你何时重新调整。或者你想要其他尝试的截图吗? – TastyLemons

回答

5

你会面临着一些问题。

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

最好是不要一个最大分辨率走了过来。这是任意的,我的选择是使用大多数人使用的屏幕分辨率。 Screen stats的例子有很多网站提供这些信息。选择一个最接近报告您的人口统计目标。

对于比不增加的分辨率只是增加的DOM元素的尺寸更大的显示器。

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

对于具有较低分辨率的显示器减少屏幕的分辨率,以适应屏幕水库没有意义给予设备额外的像素渲染,这是不会被看到的。我亲自重新渲染所有图形,以便在加载图像时更正低分辨率显示的分辨率。再次,这是为了阻止设备渲染比需要更多的像素(移动设备无法处理太多)以及平滑方法还有很多不足之处(即它完全是错误的)。请参阅此视频以解释为什么要解释为什么Computer colour is broken

小心降低分辨率。如果你有一个100byte的像素图像,并且需要将它缩小到93by93,它不会看起来很好。为每个渲染元素仔细选择图形大小,以便尽可能减少最常见的一组分辨率,您将显示在其中。

还允许在播放字段大小的一些摆动空间,他们并不全部必须是完全相同的尺寸。

更好的是要存储的图形作为基于矢量的图像(如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 

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. 
} 

你也可以做它依赖于有规模和您的个人喜好为他们如何看平滑,减少和平滑扩展或不平滑的大的小的个体呈现的物品。

这应该给你所有你需要渲染图形的所有设备

+0

真棒解答!非常感谢你。 – TastyLemons

+0

由于某种原因,画布未居中。它位于屏幕的左下角。缩放似乎完美,但画布的位置是错误的。 – TastyLemons

+1

@TastyLemons好的,我会检查是否有错误。大约一个小时。 – Blindman67

0

努力落实Blindman67的方法后,我发现了一个更快,更短的方式使用CSS,而不是绘制每个图像来实现这一相同的结果以不同的方式使用修改的drawImage()函数。

这里是更简单的方法,请告诉我,如果我忽略了上述方法确实解决的任何问题,尽管我相信所有问题都得到解决。

- >给定定义为帆布:

canvas 

其等于在html页面画布元件。

希望的原始分辨率缩放到(参见Blindman67的澄清的答案,如果需要的话)被定义为:

devW, devH 
//Noting that these values usually correspond to window.innerWidth, window.innerHeight, respectively. 

(1)对于规模填充:定义为

resW, resH 

器件尺寸屏幕上,裁剪掉多余的东西:

let f = Math.max(window.innerWidth/resW, window.innerHeight/resH); 
//f is the factor by which we redefine our canvas size as show in the code in the following lines: 
//Change the canvas elements 'direct' width and height properties 
canvas.width = Math.floor(devW/f); 
canvas.height = Math.floor(devH/f); 
//Change the canvas elements 'css' width and height properties to fill 
// the entire page. 
canvas.style.width = '100%'; 
canvas.style.height = '100%'; 

(2)对于装配画布c ontent到屏幕上,它是由单纯简单得多:

集:

//Changing the 'css' canvas width size, making sure the width is always fitting. 
canvas.style.width = '100%'; 

然后:

//Making the direct canvas width and height the desired native resolution's size 
canvas.width = resW; 
canvas.height = resH; 

现在CSS自动进行缩放,而不是依靠的drawImage复杂功能的护理。

尽管对于游戏(画布的主要功能),由于如果用户调整其窗口的大小,将会出现在屏幕上,因此要填充的比例尺更加可取。另一方面,如果您使用比例来填充,玩家可以获得更加身临其境的视野,没有空白区域或没有缩放的时候,以及其他屏幕较大的玩家有优势的问题。

据我所知,这是非常晚,但经过几个月寻找解决方案不太复杂,我终于找到了答案。所以对于其他人可能需要这个参考,我想在这里保留这个答案。

非常感谢您的阅读。