每当屏幕被触动时,我想给玩家一个冲动,最小的冲动或最大的冲动
如果屏幕被轻拍,则最小脉冲应该是例如. y = 50.
如果屏幕保持,则表示手指长度在屏幕上,最大值应为例如. y = 100.
但是玩家也应该能够在最小和最大高度之间跳跃,屏幕不长,但也不短短,玩家只能得到y = 70的冲动.
如果屏幕保持,播放器应该跳到最大高度,掉下来,如果它再次与平台接触,则应该跳转,因为您仍然按住屏幕.
我已经尝试了这个线程中的建议答案: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这样的状态.现在,要确定字符是否在地面上,您只需设置isOnTheGround = true,当字符与平台进行联系时,在didEndContact中设置为false …但是有些情况下,当与空气(如侧面接触)…
编辑:
我改变了代码,让玩家在按下时跳跃.结果如下:
重要:
实际的平台实施和联系人处理取决于你,这并没有被测试.此示例的唯一目的是向您展示如何在按下时跳转.目前,physicsWorld.speed设置为0.5,使动画更慢,因为它更容易调试,但可以将其更改为默认值(1.0).
所以,从图像可以看出,当玩家在第一个平台上时,会出现一些小跳跃(通过简单的敲击或短按).然后(玩家还在第一个平台上)长按了,玩家已经跳上了第二个平台.之后,又做了一个长时间的新闻,但这次没有释放,玩家开始从一个平台跳到另一个平台,最大的力量.
这需要大量的调整和适当的平台&联系检测,但它可以给你一个想法如何实现跳跃你问.