Sprite Kit set Min. y Max. para saltar

Quiero mover un SKSpriteNode en el Y-Axis El SKSpriteNode llamado Player no tiene Velocity . El jugador solo puede saltar si una plataforma está en contacto.

Cada vez que se toca la pantalla, quiero darle al jugador un impulso con un impulso mínimo o un impulso máximo

Si la pantalla se toca brevemente, el impulso mínimo debe ser, por ejemplo, y = 50 . Si la pantalla está en espera, significa que el dedo está en la pantalla por mucho time, el máximo debe ser, por ejemplo, y = 100 .

Pero el jugador también debería poder saltar entre la altura mínima y máxima, por ejemplo, si la pantalla no es larga pero tampoco se presiona brevemente, el jugador solo obtendrá un impulso de y = 70 .

Si la pantalla está en espera, el jugador debe saltar a su altura máxima, caer, y si está nuevamente en contacto con la plataforma, debe saltar, porque todavía mantiene presionada la pantalla.

Ya lo he intentado con la respuesta sugerida en este Tema: StackOverFlow Pero esto no da el salto Mínimo, tampoco hay salto de prensa.

Para mayor claridad: el impulso no debe ser después de que se haya hecho el toque, sino que mientras se toca. Cuanto más time sostenga, más largo será el salto.

 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 } } 

Aquí hay un ejemplo práctico sobre cómo hacer algo así:

  • salto largo presionado basado en la duración de la prensa
  • corto (un toque salto)
  • restringir carácter para saltar mientras está en el air
  • mantener el carácter saltando mientras el dedo está en la pantalla

     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.networkingColor() 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 } } } } 

Tenga en count que este es un ejemplo simple, y en la aplicación real probablemente tendrá que manejar estados como isOnTheGround de una manera diferente. En este momento, para determinar si el personaje está en el suelo, simplemente establece isOnTheGround = true cuando el personaje hace un contacto con la plataforma, y ​​lo establece en false en didEndContact … Pero hay situaciones cuando el personaje puede estar en contacto con la plataforma mientras está en el air (por ejemplo, contacto lateral) …

EDITAR:

Cambié el código para que el jugador salte mientras estaba presionado. Aquí está el resultado:

introduzca la descripción de la imagen aquí

Importante:

La implementación real de la plataforma y el event handling los contactos dependen de usted y esto no se testing. El único propósito de este ejemplo es mostrarle cómo saltar mientras está presionado. Actualmente, physicsWorld.speed se establece en 0.5 para hacer que la animation sea más lenta porque es más fácil de depurar de esa forma, pero puedes cambiar esto por el valor pnetworkingeterminado (1.0).

Por lo tanto, como puede ver en la image, mientras el jugador está en la primera plataforma, se presentan algunos saltos pequeños (con un simple toque o una presión corta). Luego (el jugador todavía está en la primera plataforma) se ha presionado mucho y el jugador ha saltado en la segunda plataforma. Después de eso, se hace otra pulsación larga, pero esta vez sin soltar, y el jugador comienza a saltar de una plataforma a otra usando la fuerza máxima.

Esto necesita una gran cantidad de ajustes y la detección adecuada de la plataforma y los contactos, pero puede darle una idea acerca de cómo implementar los saltos que le preguntaron.