Sprite Kit:有没有办法禁用缩放模式并编码你想要发生的事情

Posted

技术标签:

【中文标题】Sprite Kit:有没有办法禁用缩放模式并编码你想要发生的事情【英文标题】:Sprite Kit: Is there a way to disable the scale mode and code what you want to happen 【发布时间】:2015-12-28 19:00:28 【问题描述】:

我正在使用 Sprite Kit,Objective C 构建一个通用应用程序。该应用程序针对 OS X 和 ios 平台。

很多人都会遇到的一个问题是对象在屏幕上的定位,因为不同的设备有不同的比例。我已经在线阅读了许多答案/帖子来解决这个问题,并得出结论,在解决这个问题时,程序员似乎只有几个选项可用,即选择可用的适当缩放模式:Aspect填充、宽高比匹配、填充、调整大小填充。

我已经尝试了所有4个,并且可以看到它们都有很多优点,但都有它们的缺点,所以它们都不是我想要的。

我已经为我正在寻找的东西提出了自己的解决方案(以下代码来自 OS X 版本,但 iOS 版本非常相似):

首先,我使用宏定义sceneDimension:

#define sceneDimension 1024

然后我删除 SKScene 文件,并使用以下代码行创建自己的场景:

@implementation AppDelegate

@synthesize window = _window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 

GameScene *scene = [[GameScene alloc] initWithSize:CGSizeMake(sceneDimension * (self.skView.bounds.size.width / MIN(self.skView.bounds.size.width, self.skView.bounds.size.height)), sceneDimension * (self.skView.bounds.size.height / MIN(self.skView.bounds.size.width, self.skView.bounds.size.height)))];

.....



.....

@end

此代码确保无论运行应用程序的设备的大小/比例如何,如果屏幕宽度较大,屏幕的右上角坐标将始终被视为 (x, 1024),或者 (1024 , y) 如果屏幕的高度更大。

这样,只要场景始终保持右上角的较小坐标为 1024,我就不必担心重新定位对象。(这与 Aspect Fit 不同,因为我不这样做'不想有信箱)

当我在 OSX 上运行应用程序时,我遇到的问题很明显。每当调整窗口大小时,仍然需要选择缩放模式,而我所追求的都不是。

因此,我希望通过使用以下代码行来覆盖程序在缩放屏幕时所做的一切:

scene.size = CGSizeMake(sceneDimension * (self.view.bounds.size.width / MIN(self.view.bounds.size.width, self.view.bounds.size.height)), sceneDimension * (self.view.bounds.size.height / MIN(self.view.bounds.size.width, self.view.bounds.size.height)))

但是,我不知道在哪里添加代码行。我曾尝试在.m 文件中的函数didApplyConstraints: 中使用这行代码:

@implementation

.....

- (void)didApplyConstraints 

    scene.size = CGSizeMake(sceneDimension * (self.view.bounds.size.width / MIN(self.view.bounds.size.width, self.view.bounds.size.height)), sceneDimension * (self.view.bounds.size.height / MIN(self.view.bounds.size.width, self.view.bounds.size.height)))


@end

这主要给出了预期的结果。但是,在鼠标拖动过程中,仍然可以看到场景正在使用前面提到的缩放模式之一进行缩放,而不是我的新功能。我还读到didApplyConstraints: 在每一帧都被调用,这是我不希望发生的——我希望在窗口大小发生变化时调用它。

有没有比didApplyConstraints: 更合适的函数呢? didChangeSize: 也不起作用,因为我更改了函数内部的大小,程序最终进入了无限循环。

谢谢!

【问题讨论】:

【参考方案1】:

听起来您尝试尝试的是 .AspectFill,但有一点不同。您想填满屏幕,但在所有设备的 x 轴上保持坐标系相同。

在进行数学运算时,您需要考虑纵横比。

我们这里只讨论纵向模式。

我们有一部宽高比为 9:16 的 iPhone 5。

我们希望 x 始终为 1024。

这意味着我们希望我们的 y 为 1820(准确地说是 1820.4444~)

现在我们有了一个宽高比为 2:3 的 iPhone 4。

这意味着我们希望 y 为 1536

因此,要获得这些数字,您需要 (1024 * height) / width

我们现在可以再次讨论纵向和横向。

以下是应用数学的方法:

let w = sceneDimension 
let h = (w * UIScreen.mainScreen().bounds.size.height) / UIScreen.mainScreen().bounds.size.width)
scene.size = CGSizeMake(w,h)

现在这意味着无论方向如何,创建场景时,最左下角的点是 (0,0),最右下角的点是 (1024,0)。

Aspect Fill 现在将填满整个屏幕,不会留下任何信箱,并且边缘不会丢失

【讨论】:

是的,但是当窗口大小改变时,我需要让场景自行调整大小。 当尺寸发生变化时,您可以通过相同的数学运算调整场景的大小。 我的答案是在 iOS 中,我不知道如何在 OS X 中获取窗口大小,但将窗口高度和宽度放在我有屏幕的地方 是的,但我不知道当尺寸发生变化时该把数学放在 哪里。哪个函数... 嗯,我相信你可以查一下

以上是关于Sprite Kit:有没有办法禁用缩放模式并编码你想要发生的事情的主要内容,如果未能解决你的问题,请参考以下文章

Sprite Kit 中的单个粒子和物理

Sprite Kit 游戏:纵向模式下的世界,横向模式下的战斗?

在 Sprite Kit 中停止 repeatActionForever

如何枚举 Sprite Kit 场景中的所有节点?

Sprite Kit 相机平滑移动,延迟

Sprite-Kit:移动SKSpriteNode