Sprite Kit套件最小。 和Max。 跳转

我想在Y-Axis轴上移动一个SKSpriteNode。 被称为Player的SKSpriteNode没有Velocity 。玩家只能在平台接触的情况下跳转。

每次触摸屏幕,我都想给玩家一个最小的冲动或最大的冲动的冲动

如果短时间点击屏幕,则最小冲动应为例如y = 50 。 如果屏幕保持,那就意味着手指在屏幕上长,最大值应该是例如y = 100

但是玩家也应该能够在最小和最大高度之间跳跃,如果对于例如屏幕不长但也没有被短时间按下,玩家应该只能得到y = 70的冲动。

如果屏幕被保持,玩家应该跳到他的最大高度,跌倒,如果它再次与平台接触,它应该跳跃,因为你仍然拿着屏幕。

我已经试过这个在这个线程中的build议的答案: StackOverFlow但是这不会给最小跳转,也没有按下跳转。

为了清楚起见:冲动不应该在水龙头完成后,而应该在水龙头冲击下。 你持有的时间越长,跳跃的时间就越长。

 import SpriteKit import GameKit struct Constants { static let minimumJumpForce:CGFloat = 40.0 static let maximumJumpForce:CGFloat = 60.0 static let characterSideSpeed:CGFloat = 18.0 } class GameScene: SKScene, SKPhysicsContactDelegate { var Player: SKSpriteNode! var Platform0: SKSpriteNode! var World: SKNode! var Camera: SKNode! var force: CGFloat = 40.0 var pressed = false var isCharacterOnGround = false ..... func SpawnPlatforms() { Platform0 = SKSpriteNode (color: SKColor.greenColor(), size: CGSize(width: self.frame.size.width , height: 25)) Platform0.position = CGPoint(x: self.frame.size.width / 2, y: -36) Platform0.zPosition = 1 Platform0.physicsBody = SKPhysicsBody(rectangleOfSize:Platform0.size) Platform0.physicsBody?.dynamic = false Platform0.physicsBody?.allowsRotation = false Platform0.physicsBody?.restitution = 0 Platform0.physicsBody?.usesPreciseCollisionDetection = true Platform0.physicsBody?.categoryBitMask = Platform0Category Platform0.physicsBody?.collisionBitMask = PlayerCategory Platform0.physicsBody?.contactTestBitMask = PlayerCategory World.addChild(Platform0) } func SpawnPlayer(){ Player = SKSpriteNode (imageNamed: "Image.png") Player.size = CGSize(width: 64, height: 64) Player.position = CGPoint(x: self.frame.size.width / 2, y: 0) Player.zPosition = 2 Player.physicsBody = SKPhysicsBody(rectangleOfSize:CGSize(width: 35, height: 50)) Player.physicsBody?.dynamic = true Player.physicsBody?.allowsRotation = false Player.physicsBody?.restitution = 0.1 Player.physicsBody?.usesPreciseCollisionDetection = true Player.physicsBody?.categoryBitMask = PlayerCategory Player.physicsBody?.collisionBitMask = Platform0Category Player.physicsBody?.contactTestBitMask = Platform0Category | Platform1Category | Platform2Category | Platform3Category | Platform4Category | Platform5Category World.addChild(Player) } func jump(force : CGFloat){ if(self.isCharacterOnGround){ self.Player.physicsBody?.applyImpulse(CGVectorMake(0, force)) self.isCharacterOnGround = false } } override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) { /* Called when a touch begins */ for touch in (touches as! Set<UITouch>) { let location = touch.locationInNode(self) self.pressed = true let timerAction = SKAction.waitForDuration(0.0) let update = SKAction.runBlock({ if(self.force < Constants.maximumJumpForce){ self.force += 2.0 }else{ self.jump(Constants.maximumJumpForce) self.force = Constants.maximumJumpForce } }) let sequence = SKAction.sequence([timerAction, update]) let repeat = SKAction.repeatActionForever(sequence) self.runAction(repeat, withKey:"repeatAction") } } override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) { for touch in (touches as! Set<UITouch>) { let location = touch.locationInNode(self) self.removeActionForKey("repeatAction") self.jump(self.force) self.force = Constants.minimumJumpForce self.pressed = false } } func didBeginContact(contact: SKPhysicsContact) { //this gets called automatically when two objects begin contact with each other let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask switch(contactMask) { case PlayerCategory | Platform0Category: //either the contactMask was the bro type or the ground type println("Contact Made0") Green = true self.isCharacterOnGround = true default: return } } 

这里是一个工作的例子,如何做到这一点:

  • 按压时间长按跳
  • 短(一个水龙头跳)
  • 限制人物在空中跳跃
  • 当手指在屏幕上时保持字符跳跃

     import SpriteKit struct Constants { static let minimumJumpForce:CGFloat = 15.0 static let maximumJumpForce:CGFloat = 30.0 static let characterSideSpeed:CGFloat = 18.0 } class GameScene: SKScene,SKPhysicsContactDelegate { let CharacterCategory : UInt32 = 0x1 << 1 let PlatformCategory : UInt32 = 0x1 << 2 let WallCategory : UInt32 = 0x1 << 3 var force: CGFloat = 16.0 //Initial force var pressed = false var isCharacterOnGround = false // Use this to prevent jumping while in the air let character = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width: 30, height:30)) let debugLabel = SKLabelNode(fontNamed: "Geneva") override func didMoveToView(view: SKView) { //Setup contact delegate so we can use didBeginContact and didEndContact methods physicsWorld.contactDelegate = self physicsWorld.speed = 0.5 //Setup borders so character can't escape from us :-) self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame) self.physicsBody?.categoryBitMask = WallCategory self.physicsBody?.collisionBitMask = CharacterCategory //Setup character character.position = CGPoint(x: 150, y: 150) character.physicsBody = SKPhysicsBody(rectangleOfSize: character.size) character.physicsBody?.categoryBitMask = CharacterCategory character.physicsBody?.contactTestBitMask = PlatformCategory character.physicsBody?.collisionBitMask = PlatformCategory | WallCategory character.physicsBody?.allowsRotation = false character.physicsBody?.dynamic = true character.physicsBody?.restitution = 0.1 self.addChild(character) generatePlatforms() debugLabel.text = " DEBUG: " debugLabel.fontColor = SKColor.whiteColor() debugLabel.fontSize = 12.0 debugLabel.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame)+100) self.addChild(debugLabel) } func generatePlatforms(){ for i in 1...4 { let position = CGPoint(x: CGRectGetMidX(frame), y: CGFloat(i)*140.0 - 100) let platform = createPlatformAtPosition(position) self.addChild(platform) } } func createPlatformAtPosition(position : CGPoint)->SKSpriteNode{ let platform = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width:frame.size.width, height:20)) platform.position = position platform.physicsBody = SKPhysicsBody( edgeFromPoint: CGPoint(x: -platform.size.width/2.0, y:platform.size.height/2.0), toPoint:CGPoint(x: platform.size.width/2.0, y: platform.size.height/2.0)) platform.physicsBody?.categoryBitMask = PlatformCategory platform.physicsBody?.contactTestBitMask = CharacterCategory platform.physicsBody?.collisionBitMask = CharacterCategory platform.physicsBody?.allowsRotation = false platform.name = "platform" platform.physicsBody?.dynamic = false platform.physicsBody?.restitution = 0.0 return platform } func jump(force : CGFloat){ if(self.isCharacterOnGround){ self.character.physicsBody?.applyImpulse(CGVectorMake(0, force)) self.character.physicsBody?.collisionBitMask = WallCategory self.isCharacterOnGround = false } } override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { self.pressed = true let timerAction = SKAction.waitForDuration(0.05) let update = SKAction.runBlock({ if(self.force < Constants.maximumJumpForce){ self.force += 2.0 }else{ self.jump(Constants.maximumJumpForce) self.force = Constants.maximumJumpForce } }) let sequence = SKAction.sequence([timerAction, update]) let repeat = SKAction.repeatActionForever(sequence) self.runAction(repeat, withKey:"repeatAction") } override func touchesEnded(touches: NSSet, withEvent event: UIEvent) { self.removeActionForKey("repeatAction") self.jump(self.force) self.force = Constants.minimumJumpForce self.pressed = false } override func update(currentTime: NSTimeInterval) { debugLabel.text = "DEBUG: onTheGround : \(isCharacterOnGround), force \(force)" if(character.position.x <= character.size.width/2.0 + 5.0 && character.physicsBody?.velocity.dx < 0.0 ){ character.physicsBody?.applyForce(CGVectorMake(Constants.characterSideSpeed, 0.0)) }else if((character.position.x >= self.frame.size.width - character.size.width/2.0 - 5.0) && character.physicsBody?.velocity.dx >= 0.0){ character.physicsBody?.applyForce(CGVectorMake(-Constants.characterSideSpeed, 0.0)) }else if(character.physicsBody?.velocity.dx > 0.0){ character.physicsBody?.applyForce(CGVectorMake(Constants.characterSideSpeed, 0.0)) }else{ character.physicsBody?.applyForce(CGVectorMake(-Constants.characterSideSpeed, 0.0)) } } func didBeginContact(contact: SKPhysicsContact) { var firstBody, secondBody: SKPhysicsBody if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask { firstBody = contact.bodyA secondBody = contact.bodyB } else { firstBody = contact.bodyB secondBody = contact.bodyA } if ((firstBody.categoryBitMask & CharacterCategory) != 0 && (secondBody.categoryBitMask & PlatformCategory != 0)) { let platform = secondBody.node as SKSpriteNode // platform.color = UIColor.redColor() let platformSurfaceYPos = platform.position.y + platform.size.height/2.0 let player = contact.bodyB.node as SKSpriteNode let playerLegsYPos = player.position.y - player.size.height/2.0 if((platformSurfaceYPos <= playerLegsYPos) ){ character.physicsBody?.collisionBitMask = PlatformCategory | WallCategory self.isCharacterOnGround = true if(self.pressed){ var characterDx = character.physicsBody?.velocity.dx character.physicsBody?.velocity = CGVector(dx: characterDx!, dy: 0.0) self.jump(Constants.maximumJumpForce) } } } } func didEndContact(contact: SKPhysicsContact) { var firstBody, secondBody: SKPhysicsBody if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask { firstBody = contact.bodyA secondBody = contact.bodyB } else { firstBody = contact.bodyB secondBody = contact.bodyA } if ((firstBody.categoryBitMask & CharacterCategory) != 0 && (secondBody.categoryBitMask & PlatformCategory != 0)) { let platform = secondBody.node as SKSpriteNode let platformSurfaceYPos = platform.position.y + platform.size.height/2.0 let player = contact.bodyB.node as SKSpriteNode let playerLegsYPos = player.position.y - player.size.height/2.0 if((platformSurfaceYPos <= playerLegsYPos) && (character.physicsBody?.velocity.dy > 0.0)){ character.physicsBody?.collisionBitMask = WallCategory self.isCharacterOnGround = false } } } } 

请注意,这是一个简单的例子,在实际的应用程序中,您可能必须以不同的方式处理isOnTheGround这样的状态。 现在,要确定angular色是否在地面上,你刚刚设置了isOnTheGround = true当angular色与平台接触,并在didEndContact中将其设置为false …但是有些情况下angular色可以与平台接触,而在空气(如侧面接触)…

编辑:

我改变了代码让玩家在按下时跳跃。 结果如下:

在这里输入图像说明

重要:

实际的平台实施和联系人处理由您决定,但未经过testing。 这个例子的唯一目的是向你展示如何在按下的同时跳转。 目前, physicsWorld.speed被设置为0.5,使animation更慢,因为它更容易debugging,但是可以将其更改为默认值(1.0)。

所以,从图像中可以看到,玩家在第一个平台上时会出现一些小跳跃(通过简单的敲击或短按)。 然后(玩家仍然在第一个平台上)长按,玩家跳上第二个平台。 之后,又一次长按,但是这一次没有放开,玩家用最大的力量从一个平台跳到另一个平台。

这需要很多的调整和适当的平台和接触检测,但它可以给你一个关于如何实现跳跃的想法,你问。