You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift4游戏适配iPad/iPhoneX时.aspectFill倾斜及碰撞坐标修正问题

Hey there! Let's work through these two issues you're hitting in your Swift 4 game—screen distortion on iPad/iPhone X and collision position correction. I've got step-by-step solutions for both:

1. Fixing AspectFill Screen Distortion on iPad & iPhone X

The tilt you're seeing is likely due to a mismatch between your fixed 750x1334 scene size and the varying aspect ratios of different devices (iPad is 4:3, iPhone X is 19.5:9, while your scene is 9:16). Here’s how to fix it:

  • Ensure Proper Scene Initialization: When loading your GameScene.sks, make sure your SKView matches the device’s screen bounds and you handle aspect ratio correctly:

    if let view = self.view as? SKView {
        guard let scene = SKScene(fileNamed: "GameScene") else { return }
        
        scene.scaleMode = .aspectFill
        view.frame = self.view.bounds
        view.ignoresSiblingOrder = true
        view.presentScene(scene)
    }
    
  • Adjust Scene Size for Device Aspect Ratio: Add this code to your GameScene’s didMove(to:) method to dynamically adjust the scene size while preserving your original aspect ratio:

    override func didMove(to view: SKView) {
        let viewRatio = view.bounds.width / view.bounds.height
        let sceneRatio = size.width / size.height
        
        if viewRatio > sceneRatio {
            // View is wider than scene—adjust height to match view width
            size = CGSize(width: view.bounds.width, height: view.bounds.width / sceneRatio)
        } else {
            // View is taller than scene—adjust width to match view height
            size = CGSize(width: view.bounds.height * sceneRatio, height: view.bounds.height)
        }
    }
    
  • Lock Interface Orientation: Double-check your Info.plist’s Supported interface orientations to ensure you’re only supporting the orientation your game is designed for (e.g., portrait). This prevents unexpected scene rotation that can cause tilt.

2. Adjusting SpriteNode Position to Stick to "Dirt Boulder" After Collision

To fix the overlapping issue and make your sprite snap to the boulder based on its direction of approach, use the physics contact’s normal and penetration depth to calculate the correct position. Here’s how:

First, make sure your physics bodies are properly configured (set categoryBitMask, contactTestBitMask, and ensure the boulder is isDynamic = false if it’s stationary). Then update your didBegin(_ contact:) method:

func didBegin(_ contact: SKPhysicsContact) {
    // Identify which bodies are the player and dirt boulder
    var player: SKSpriteNode?
    var boulder: SKSpriteNode?
    
    if (contact.bodyA.node?.name == "player" && contact.bodyB.node?.name == "dirt boulder") {
        player = contact.bodyA.node as? SKSpriteNode
        boulder = contact.bodyB.node as? SKSpriteNode
    } else if (contact.bodyB.node?.name == "player" && contact.bodyA.node?.name == "dirt boulder") {
        player = contact.bodyB.node as? SKSpriteNode
        boulder = contact.bodyA.node as? SKSpriteNode
    }
    
    guard let playerSprite = player, let boulderSprite = boulder else { return }
    
    // Get collision data: normal (direction of collision) and penetration depth (overlap distance)
    let contactNormal = contact.contactNormal
    let penetration = contact.penetrationDepth
    
    // Calculate correction vector to move player out of overlap
    // Reverse the normal because it points from the boulder to the player
    let correction = CGVector(dx: contactNormal.dx * penetration, dy: contactNormal.dy * penetration)
    playerSprite.position = CGPoint(
        x: playerSprite.position.x - correction.dx,
        y: playerSprite.position.y - correction.dy
    )
    
    // Stop player movement immediately
    playerSprite.physicsBody?.velocity = .zero
}

Why this works:

  • contactNormal: A vector pointing from the boulder to the player, telling you exactly which direction the collision came from.
  • penetrationDepth: The distance the player has overlapped with the boulder—we use this to move the player just far enough to eliminate the overlap.

This method is far more accurate than hardcoding position adjustments because it uses the physics engine’s precise collision data.

内容的提问来源于stack exchange,提问作者user3301173

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:08:03