SpriteKit 物理在不同的屏幕分辨率上不一致
SpriteKit Physics Inconsistent On Different Screen Resolution
我在玩 SpriteKit 游戏时遇到了一些问题。我正在尝试做一个平台游戏风格的游戏,玩家点击屏幕让角色跳跃。我通过以下方式实现了这一目标:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// reset the velocity each jump, so that a constant impulse is always applied
self.player.physicsBody.velocity = CGVectorMake(0, 0);
// jump the player up
[self.player.physicsBody applyImpulse:CGVectorMake(0, PLAYER_JUMP_HEIGHT)];
}
PLAYER_JUMP_HEIGHT
只是一个常数。我还设置了质量恒定的播放器。
这在 iPad 模拟器上效果很好,我在模拟器上进行了大部分初始测试。然而,在调整我的代码以适应设备分辨率(对于手机等)之后,我的物理学现在看起来很不正常,特别是在 iPhone 4S 模拟器上。同样的冲动现在使玩家跳得很高,而且他们似乎也更快地从平台等物体上掉下来,比以前更呈线性曲线。
我通过首先设置场景的缩放模式来缩放我的场景以适应多个设备:
scene.scaleMode = SKSceneScaleModeResizeFill;
我还想出了一种方法来缩放游戏中的所有其他内容,方法是将当前设备的分辨率与 iPad 的分辨率进行比较,然后除以得到一个比例因子以乘以所有内容。因此,如果 iPad 屏幕宽度为 2048,如果我在 iPhone 4S 上 运行,比例因子将为 960 / 2048 = 0.46。通过这种方式,我可以使用一组常量来设计游戏,这些常量可以跨所有设备分辨率进行缩放,而不会出现其他缩放模式的裁剪或其他缩放问题。
我很困惑这可能是什么。我试过将玩家质量和跳跃高度乘以屏幕比例因子,在所有可能的组合中,都无济于事。我也试过弄乱 physicsWorld 的重力和速度,但也没用。如果有人有处理此问题的经验并愿意分享,我们将不胜感激。谢谢!
你的问题需要考虑几个因素,包括不同设备的不同分辨率,重力和动量。为什么是势头?因为在applyImpulse:(CGVector)impulse
中,impulse是一个向量,描述了增加了多少动量。因此,简单地在 PLAYER_JUMP_HEIGHT
上乘以比例因子是没有用的。
感谢 ,我们可以使用一个名为 'pixel to unit' 的比率来计算需要多少 dy
来生成脉冲向量。
下面讲解如何让玩家跳转常量PLAYER_JUMP_HEIGHT
。你可能想根据不同的分辨率自己调整它,这次你的比例因子应该起作用了。
#define kScale ([[UIScreen mainScreen] bounds].size.height) / 1024.0
const CGFloat PLAYER_JUMP_HEIGHT = 200.0;
- (void)didMoveToView:(SKView *)view
{
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
// Print useful info
NSLog(@"scale: %.3f", kScale);
NSLog(@"total height: %.1f", self.frame.size.height);
NSLog(@"jump height: %.1f%%", kScale * PLAYER_JUMP_HEIGHT / self.frame.size.height * 100);
// Let player jump over the bar
SKSpriteNode *bar = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(CGRectGetMaxY(self.frame), 1.0)];
bar.position = CGPointMake(CGRectGetMidX(self.frame), PLAYER_JUMP_HEIGHT * kScale);
[self addChild:bar];
self.player = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(kScale * 50.0, kScale * 50.0)];
self.player.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(kScale * 50.0, kScale * 50.0)];
self.player.physicsBody.mass = 0.25;
self.player.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)/5.0);
[self addChild:self.player];
// Pixel to unit
ptu = 1.0 / sqrt([SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(1.0, 1.0)].mass);
}
在上面的代码中,我们首先设置常量PLAYER_JUMP_HEIGHT
,一个指示屏幕上200点有多高的条,一个player
和比率ptu
.
然后计算dy
并将其应用于冲量:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// reset the velocity each jump, so that a constant impulse is always applied
self.player.physicsBody.velocity = CGVectorMake(0, 0);
self.physicsWorld.gravity = CGVectorMake(0, kScale * (-9.8));
// jump the player up
CGFloat dy = self.player.physicsBody.mass * sqrt(2 * (-self.physicsWorld.gravity.dy) * (kScale * PLAYER_JUMP_HEIGHT * ptu));
[self.player.physicsBody applyImpulse:CGVectorMake(0, dy)];
}
这是sample project(过时)的演示,运行并播放它。你会发现盒子精灵实际上并没有跳过红色条,而是略低了一点。我觉得是重力原因。
多处代码更新:
为不同的设备定义kScale
宏以便快速测试。仅适用于纵向。
在需要的地方添加 kScale
(跳跃高度、球员体型和重力!)。它现在应该以相同的速度跳跃自适应高度。
我在玩 SpriteKit 游戏时遇到了一些问题。我正在尝试做一个平台游戏风格的游戏,玩家点击屏幕让角色跳跃。我通过以下方式实现了这一目标:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// reset the velocity each jump, so that a constant impulse is always applied
self.player.physicsBody.velocity = CGVectorMake(0, 0);
// jump the player up
[self.player.physicsBody applyImpulse:CGVectorMake(0, PLAYER_JUMP_HEIGHT)];
}
PLAYER_JUMP_HEIGHT
只是一个常数。我还设置了质量恒定的播放器。
这在 iPad 模拟器上效果很好,我在模拟器上进行了大部分初始测试。然而,在调整我的代码以适应设备分辨率(对于手机等)之后,我的物理学现在看起来很不正常,特别是在 iPhone 4S 模拟器上。同样的冲动现在使玩家跳得很高,而且他们似乎也更快地从平台等物体上掉下来,比以前更呈线性曲线。
我通过首先设置场景的缩放模式来缩放我的场景以适应多个设备:
scene.scaleMode = SKSceneScaleModeResizeFill;
我还想出了一种方法来缩放游戏中的所有其他内容,方法是将当前设备的分辨率与 iPad 的分辨率进行比较,然后除以得到一个比例因子以乘以所有内容。因此,如果 iPad 屏幕宽度为 2048,如果我在 iPhone 4S 上 运行,比例因子将为 960 / 2048 = 0.46。通过这种方式,我可以使用一组常量来设计游戏,这些常量可以跨所有设备分辨率进行缩放,而不会出现其他缩放模式的裁剪或其他缩放问题。
我很困惑这可能是什么。我试过将玩家质量和跳跃高度乘以屏幕比例因子,在所有可能的组合中,都无济于事。我也试过弄乱 physicsWorld 的重力和速度,但也没用。如果有人有处理此问题的经验并愿意分享,我们将不胜感激。谢谢!
你的问题需要考虑几个因素,包括不同设备的不同分辨率,重力和动量。为什么是势头?因为在applyImpulse:(CGVector)impulse
中,impulse是一个向量,描述了增加了多少动量。因此,简单地在 PLAYER_JUMP_HEIGHT
上乘以比例因子是没有用的。
感谢 dy
来生成脉冲向量。
下面讲解如何让玩家跳转常量PLAYER_JUMP_HEIGHT
。你可能想根据不同的分辨率自己调整它,这次你的比例因子应该起作用了。
#define kScale ([[UIScreen mainScreen] bounds].size.height) / 1024.0
const CGFloat PLAYER_JUMP_HEIGHT = 200.0;
- (void)didMoveToView:(SKView *)view
{
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
// Print useful info
NSLog(@"scale: %.3f", kScale);
NSLog(@"total height: %.1f", self.frame.size.height);
NSLog(@"jump height: %.1f%%", kScale * PLAYER_JUMP_HEIGHT / self.frame.size.height * 100);
// Let player jump over the bar
SKSpriteNode *bar = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(CGRectGetMaxY(self.frame), 1.0)];
bar.position = CGPointMake(CGRectGetMidX(self.frame), PLAYER_JUMP_HEIGHT * kScale);
[self addChild:bar];
self.player = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(kScale * 50.0, kScale * 50.0)];
self.player.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(kScale * 50.0, kScale * 50.0)];
self.player.physicsBody.mass = 0.25;
self.player.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)/5.0);
[self addChild:self.player];
// Pixel to unit
ptu = 1.0 / sqrt([SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(1.0, 1.0)].mass);
}
在上面的代码中,我们首先设置常量PLAYER_JUMP_HEIGHT
,一个指示屏幕上200点有多高的条,一个player
和比率ptu
.
然后计算dy
并将其应用于冲量:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// reset the velocity each jump, so that a constant impulse is always applied
self.player.physicsBody.velocity = CGVectorMake(0, 0);
self.physicsWorld.gravity = CGVectorMake(0, kScale * (-9.8));
// jump the player up
CGFloat dy = self.player.physicsBody.mass * sqrt(2 * (-self.physicsWorld.gravity.dy) * (kScale * PLAYER_JUMP_HEIGHT * ptu));
[self.player.physicsBody applyImpulse:CGVectorMake(0, dy)];
}
这是sample project(过时)的演示,运行并播放它。你会发现盒子精灵实际上并没有跳过红色条,而是略低了一点。我觉得是重力原因。
多处代码更新:
为不同的设备定义
kScale
宏以便快速测试。仅适用于纵向。在需要的地方添加
kScale
(跳跃高度、球员体型和重力!)。它现在应该以相同的速度跳跃自适应高度。