我怎样才能让我的玩家精灵在空中被控制时更自然地掉落

问题描述 投票:0回答:0

基本上,当我的球员按下按钮跳跃时,会向球施加一种冲动使其跳跃。问题是当玩家在半空中使用操纵杆向左或向右移动时,球不会自然落到地面,而是需要一段时间才能落地。我希望有人能够帮助我稍微调整一下物理特性,使球仍然像在地面上一样表现,但也让它在跳跃后正常下落,而没有所有这些悬挂时间。

import UIKit
import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {
    
    private var ball: SKShapeNode!
    private var floor = SKSpriteNode()
    private var wall = SKSpriteNode()
    private var ceiling = SKSpriteNode()
    private var wall2 = SKSpriteNode()
    private var joystickHandleDefaultPosition: CGPoint!
   
    let ballCategory:UInt32 = 0x1 << 0
    let floorCategory:UInt32 = 0x1 << 2
    let wallCategory:UInt32 = 0x1 << 3
    
    var canJump = true
    var canDash = false
    var facing = "right"
    var joystickLocation = CGPoint()
    
    override func didMove(to view: SKView) {
        
        physicsWorld.contactDelegate = self
        setupBall()
        setupJoystick()
        setupJumpButton()
        addFloor()
        
        ball = SKShapeNode(circleOfRadius: 20)
        ball.position = CGPoint(x: frame.midX, y: frame.midY)
        ball.fillColor = SKColor.red

        ball.physicsBody = SKPhysicsBody(circleOfRadius: 22)
        ball.physicsBody?.affectedByGravity = true
        ball.physicsBody?.allowsRotation = false
        ball.physicsBody?.restitution = 0.0
        ball.physicsBody?.friction = 1.0

        ball.physicsBody?.categoryBitMask = ballCategory
        ball.physicsBody?.contactTestBitMask = floorCategory | wallCategory
        ball.physicsBody?.collisionBitMask = floorCategory | wallCategory

        addChild(ball)
        
        let distance = (frame.maxX - 80) - (frame.minX + 80)
        let floorWidth = distance  // to cover the width of both walls

        
        floor = SKSpriteNode(color: .white, size: CGSize(width: floorWidth, height: 20))
        floor.position = CGPoint(x: frame.midX, y: -140)
        floor.physicsBody = SKPhysicsBody(rectangleOf: floor.size)
        floor.physicsBody?.isDynamic = false
        floor.physicsBody?.categoryBitMask = floorCategory
        floor.physicsBody?.friction = 1.0
        floor.physicsBody?.restitution = 0.0
        floor.physicsBody?.affectedByGravity = false
        
        floor.physicsBody?.contactTestBitMask = ballCategory
        floor.physicsBody?.collisionBitMask = ballCategory
        addChild(floor)
        print(floor.physicsBody?.node?.position as Any)
        print(floor.physicsBody?.node?.frame.size as Any)
        
        wall = SKSpriteNode(color: .white, size: CGSize(width: 20, height: 600))
        wall.position = CGPoint(x: frame.maxX - 80 - (wall.size.width / 2), y: floor.position.y + (floor.size.height / 2) + (wall.size.height / 2))
        wall.physicsBody = SKPhysicsBody(rectangleOf: wall.size)
        wall.physicsBody?.isDynamic = false
        wall.physicsBody?.categoryBitMask = wallCategory
        wall.physicsBody?.friction = 1.0
        wall.physicsBody?.restitution = 0.0
        wall.physicsBody?.affectedByGravity = false
        wall.physicsBody?.contactTestBitMask = ballCategory
        wall.physicsBody?.collisionBitMask = ballCategory
        addChild(wall)
        wall2 = SKSpriteNode(color: .white, size: CGSize(width: 20, height: 600))
        wall2.position = CGPoint(x: frame.minX + 80 + (wall2.size.width / 2), y: floor.position.y + (floor.size.height / 2) + (wall2.size.height / 2))

        wall2.physicsBody = SKPhysicsBody(rectangleOf: wall2.size)
        wall2.physicsBody?.isDynamic = false
        wall2.physicsBody?.categoryBitMask = wallCategory
        wall2.physicsBody?.friction = 1.0
        wall2.physicsBody?.restitution = 0.0
        wall2.physicsBody?.affectedByGravity = false
        wall2.physicsBody?.contactTestBitMask = ballCategory
        wall2.physicsBody?.collisionBitMask = ballCategory
        addChild(wall2)
        
        ceiling = SKSpriteNode(color: .white, size: CGSize(width: floorWidth, height: 20))
        ceiling.position = CGPoint(x: frame.midX, y: wall.position.y + (wall.size.height / 2) + (ceiling.size.height / 2))


        ceiling.physicsBody = SKPhysicsBody(rectangleOf: ceiling.size)
        ceiling.physicsBody?.isDynamic = false
        ceiling.physicsBody?.categoryBitMask = wallCategory
        ceiling.physicsBody?.contactTestBitMask = ballCategory
        addChild(ceiling)


        
       
        physicsWorld.gravity = CGVector(dx: 0, dy: -9.8) // set the gravity vector
        let origin = CGPoint(x: 0, y: 0)
        
      //  let frameyWidth: CGFloat = 200
       // let frameyHeight: CGFloat = 300
     //   let framey = CGRect(x: 0, y: size.height - frameyHeight, width: frameyWidth, height: frameyHeight)
       
      //  physicsBody = SKPhysicsBody(edgeLoopFrom: framey) // add physics body to the scene's frame

    }
    
    private func setupBall() {
       
        
       
     
        
    }
    
    private func setupJoystick() {
        let joystickBackground = SKShapeNode(circleOfRadius: 80)
        joystickBackground.position = CGPoint(x: (frame.midX - 120), y: -350)
        joystickBackground.strokeColor = SKColor.white
        joystickBackground.lineWidth = 4.0
        joystickBackground.name = "joystickBackground"
       
        addChild(joystickBackground)
        
        let joystickHandle = SKShapeNode(circleOfRadius: 50)
        joystickHandle.position = CGPoint(x: (frame.midX - 120), y: -350)
        joystickHandle.fillColor = SKColor.white
        joystickHandle.strokeColor = SKColor.white
        joystickHandle.lineWidth = 2.0
        joystickHandle.name = "joystickHandle" // add name property
        joystickHandleDefaultPosition = joystickHandle.position
        addChild(joystickHandle)
    }
    
    private func setupJumpButton() {
        let jumpButton = SKShapeNode(circleOfRadius: 60)
        jumpButton.position = CGPoint(x: frame.midX + 160, y: -350)
        jumpButton.fillColor = SKColor.green
        jumpButton.name = "jumpButton" // add name property
        addChild(jumpButton)
    }
    
    func addFloor() {
     
    }



    func activateDash(){
        if facing == "right"{
            let dashImpulse = CGVector(dx: 20, dy: 2)
            ball.physicsBody?.applyImpulse(dashImpulse)
            
        }else if facing == "left"{
            let dashImpulse = CGVector(dx: -20, dy: 2)
            ball.physicsBody?.applyImpulse(dashImpulse)
        }
        
    }
 
    
    private func handleJumpButton() {
        let jumpImpulse = CGVector(dx: 0, dy: 70.0) // adjust the impulse strength as needed
        if canJump == true{
            ball.physicsBody?.applyImpulse(jumpImpulse)
            canJump = false
            canDash = true
        }else if canJump == false{
            if canDash == true{
                print("dash")
                canDash = false
                print(facing)
                activateDash()
            }
        }
    }
    
    private func handleJoystick(_ location: CGPoint) {
        let joystickPosition = CGPoint(x: (frame.midX - 120), y: -350)
        let dx = location.x - joystickPosition.x
        let dy = location.y - joystickPosition.y
        let angle = atan2(dy, dx)
        let length: CGFloat = 50.0
        
        let xDist = length * cos(angle)
        let yDist = length * sin(angle)
        
        let joystickHandle = childNode(withName: "joystickHandle") as! SKShapeNode
        joystickHandle.position = CGPoint(x: joystickPosition.x + xDist, y: joystickPosition.y + yDist)
        
        let speed: CGFloat = 500.0
        var velocity = CGVector(dx: 0, dy: 0)
        
        if xDist >= 0 {
            velocity.dx = speed
            facing = "right"
        } else {
            velocity.dx = -speed
            facing = "left"
        }
        
        ball.physicsBody?.velocity = velocity
        
    }

   

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in: self)
            let joystickBackground = childNode(withName: "joystickBackground") as! SKShapeNode
            let distance = location.distance(to: joystickBackground.position)
            let angle = joystickBackground.position.angle(to: location)
            let maxDistance: CGFloat = 50.0
            
            if distance <= maxDistance {
                handleJoystick(location)
            } else {
                let xDist = maxDistance * cos(angle)
                let yDist = maxDistance * sin(angle)
                let joystickHandle = childNode(withName: "joystickHandle") as! SKShapeNode
                joystickHandle.position = CGPoint(x: joystickBackground.position.x + xDist, y: joystickBackground.position.y + yDist)
                handleJoystick(joystickHandle.position)
            }
        }
    }


    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in: self)
            let jumpButton = childNode(withName: "jumpButton")!
            if jumpButton.contains(location) {
                handleJumpButton()
            }
        }
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        let joystickHandle = childNode(withName: "joystickHandle") as! SKShapeNode
        let joystickPosition = CGPoint(x: (frame.midX - 120), y: -350)
        
        // Snap the joystick handle back to its original position
        let moveJoystickHandle = SKAction.move(to: joystickPosition, duration: 0.1)
        joystickHandle.run(moveJoystickHandle)
    }
    
    func didBegin(_ contact: SKPhysicsContact) {
        print("contact happened")
       // print("didBeginContact entered for \(String(describing: contact.bodyA.node?.name)) and \(String(describing: contact.bodyB.node?.name))")
    
               
      
  
   
        let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
   
        switch contactMask {
        case ballCategory | floorCategory:
           print("ball and floor have contacted.")
           let ballNode = contact.bodyA.categoryBitMask == ballCategory ? contact.bodyA.node : contact.bodyB.node
           let floorNode = contact.bodyA.categoryBitMask == floorCategory ? contact.bodyA.node : contact.bodyB.node
            canJump = true
      
            
            
            
            
        default:
            print ("default")
            
        
            
        
        }
    }


   
}

extension CGPoint {
    func distance(to point: CGPoint) -> CGFloat {
        return sqrt(pow(point.x - x, 2) + pow(point.y - y, 2))
    }
    
    func angle(to point: CGPoint) -> CGFloat {
        return atan2(point.y - y, point.x - x)
    }
}

swift xcode game-physics
© www.soinside.com 2019 - 2024. All rights reserved.