我有一个问题,我在更新功能中使用以下代码根据加速度计数据移动角色,如下所示:
let currentX = self.player.position.x
if motionManager.isAccelerometerAvailable == true {
motionManager.startAccelerometerUpdates(to: OperationQueue.current!, withHandler: {
data, error in
self.destX = currentX + CGFloat((data?.acceleration.x)! * 40)
print(CGFloat((data?.acceleration.x)!))
})
}
player.position.x = destX
最初我使用SKAction.moveTo移动播放器,但为了测试目的已将其删除。
这没问题,但问题是,我有一个声音在一个不可见物体碰撞时被播放,当启用它时,它发送加速度计都很有趣。没有特定的模式,但过了一会儿,玩家通常会粘在屏幕的两侧,或只是在中间盘旋,加速度计对运动没有任何影响。
我正在使用
播放声音let playSound = SKAction.playSoundFileNamed("phaserDown3.mp3", waitForCompletion: false)
在文件的顶部,然后在碰撞时调用run。
完整的代码在这里http://pastebin.com/f6kWTnr7,我在这里https://youtu.be/tcGYyrKE4QY制作了一个关于这个问题的小视频 - 你会看到,在这种情况下,当得分大约为15时,它会坚持到离开一点点,然后恢复正常然后向右边。它并不总是在15分,它可能很快甚至更晚都没有一致性。
非常感谢任何意见,谢谢你提前
答案 0 :(得分:0)
看看这个更新的场景,一些主要的变化是我将你的3个单独的块组合成1个SKNode,这样我只需要移动单个SKNode,然后我将它设置为你在结束时得分的位置联系,而不是开始。您还可以看到滚动完成时块现在已经死亡,滚动后背景效率更高。如果您对更改有任何其他问题,请随时提出。
//
// GameScene.swift
// SpriteKitSimpleGame
//
// Created by James Leist on 28/11/2016.
// Copyright © 2016 James Leist. All rights reserved.
//
import SpriteKit
import CoreMotion
var motionManager = CMMotionManager()
enum BodyType:UInt32 {
case player = 1
case score = 2
case dontCollide = 4
case sides = 8
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var killNodes = [SKNode]()
//let player = SKSpriteNode(imageNamed: "Airplane")
let player = SKSpriteNode(color: .green, size: CGSize(width:32,height:32))
var bg1:SKSpriteNode!
var bg2:SKSpriteNode!
let block = SKNode()
let blockHeight = 50
var currentScore = 0
var scoreLabel:SKLabelNode!
let playSound = SKAction.playSoundFileNamed("phaserDown3.mp3", waitForCompletion: false)
let move = SKAction.move(by:CGVector(dx:0,dy:-4 * 60),duration:1) //this means we move 4 every 1/60 of a second
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
backgroundColor = SKColor.white
addScrollingBG()
createRandomBlock()
addRandomBlocks1()
// sideRestraints()
scoreLabel = SKLabelNode(fontNamed: "Copperplate-Bold")
scoreLabel.text = String(currentScore)
scoreLabel.fontSize = 80
scoreLabel.position = CGPoint(x: frame.size.width - 60, y: frame.size.height - 60)
scoreLabel.zPosition = 20
self.addChild(scoreLabel)
player.name = "Player"
player.zPosition = 15
player.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
// player.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "Airplane"), size: CGSize(width: player.size.width, height: player.size.height))
player.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: player.size.width, height: player.size.height))
player.physicsBody?.affectedByGravity = false
player.physicsBody!.categoryBitMask = BodyType.player.rawValue
player.physicsBody!.contactTestBitMask = BodyType.score.rawValue | BodyType.sides.rawValue
player.physicsBody!.collisionBitMask = 0
addChild(player)
startAccelerometer()
}
func startAccelerometer()
{
if motionManager.isAccelerometerAvailable == true {
motionManager.startAccelerometerUpdates(to: OperationQueue.current!, withHandler: {
[weak self] data, error in
guard let strongSelf = self else {return}
var destX = UInt32(strongSelf.player.position.x + CGFloat((data?.acceleration.x)! * 40))
// Called before each frame is rendered */
if destX <= 0 {
destX = 0
}
else if destX >= UInt32(strongSelf.frame.size.width) {
destX = UInt32(strongSelf.frame.size.width)
}
strongSelf.player.position.x = CGFloat(destX)
print(CGFloat((data?.acceleration.x)!))
})
}
}
func addScrollingBG() {
bg1 = SKSpriteNode(imageNamed: "bgPlayScene")
bg1 = SKSpriteNode(color:.blue,size:self.size)
bg1.anchorPoint = CGPoint.zero
bg1.position = CGPoint(x: 0, y: 0)
// bg1.size = CGSize(width: frame.size.width, height: frame.size.height)
bg1.zPosition = 0
addChild(bg1)
bg2 = SKSpriteNode(imageNamed: "bgPlayScene")
bg2 = SKSpriteNode(color:.purple,size:self.size)
bg2.anchorPoint = CGPoint.zero
bg2.position = CGPoint(x: 0, y: bg1.size.height)
// bg2.size = CGSize(width: frame.size.width, height: frame.size.height)
bg2.zPosition = 0
self.addChild(bg2)
setupBackgroundAnimation()
}
func setupBackgroundAnimation()
{
let reset = SKAction.customAction(withDuration: 1,actionBlock:
{
node,time in
guard let sNode = node as? SKSpriteNode else {return}
sNode.position = sNode.position.y <= -sNode.size.height ?
CGPoint(x: sNode.position.x, y: sNode.position.y + sNode.size.height * 2) : sNode.position
})
let scroll = SKAction.repeatForever(SKAction.group([move,reset]))
bg1.run(scroll)
bg2.run(scroll)
}
func createRandomBlock()
{
block.position = CGPoint(x:0,y:size.height + CGFloat(blockHeight))
//let partialBlock = SKSpriteNode(imageNamed: "block")
let partialBlock = SKSpriteNode(color:.yellow, size:CGSize(width: 1, height: blockHeight))
let blockLeft1 = partialBlock.copy() as! SKSpriteNode
blockLeft1.name = "left"
blockLeft1.anchorPoint = CGPoint.zero
blockLeft1.size = CGSize(width: 1, height: blockHeight)
blockLeft1.zPosition = 5;
blockLeft1.position = CGPoint.zero
block.addChild(blockLeft1)
let leftBody = SKPhysicsBody(rectangleOf: blockLeft1.size)
leftBody.affectedByGravity = false
leftBody.categoryBitMask = BodyType.sides.rawValue
leftBody.contactTestBitMask = 0
leftBody.collisionBitMask = 0
leftBody.isDynamic = false
blockLeft1.physicsBody = leftBody
let blockRight1 = partialBlock.copy() as! SKSpriteNode
blockRight1.color = .green
blockRight1.anchorPoint = CGPoint.zero
blockRight1.name = "right"
blockRight1.size = CGSize(width: 1, height: blockHeight)
blockRight1.zPosition = 5;
blockRight1.position = CGPoint(x:size.width,y:0)
block.addChild(blockRight1)
let rightBody = SKPhysicsBody(rectangleOf: blockRight1.size)
rightBody.affectedByGravity = false
rightBody.categoryBitMask = BodyType.sides.rawValue
rightBody.contactTestBitMask = 0
rightBody.collisionBitMask = 0
rightBody.isDynamic = false
blockRight1.physicsBody = rightBody
let scoreBody = SKPhysicsBody(rectangleOf:CGSize(width:Int(frame.size.width),height:blockHeight))
scoreBody.affectedByGravity = false
scoreBody.categoryBitMask = BodyType.score.rawValue
scoreBody.contactTestBitMask = 0
scoreBody.collisionBitMask = 0
scoreBody.isDynamic = false
block.physicsBody = scoreBody
}
func addRandomBlocks1() {
let randomLeftWidth : UInt32 = arc4random_uniform(UInt32(size.width) - 50)
let randomRightWidth : UInt32 = arc4random_uniform((UInt32(size.width) - randomLeftWidth) - 50)
guard let newBlock = block.copy() as? SKNode else {return} //ifw e do not have a node return
if let leftBlock = newBlock.childNode(withName:"left") as? SKSpriteNode
{
leftBlock.xScale = CGFloat(randomLeftWidth)
}
if let rightBlock = newBlock.childNode(withName:"right") as? SKSpriteNode
{
rightBlock.xScale = -CGFloat(randomRightWidth)
}
let addRandom = SKAction.customAction(withDuration: 0, actionBlock:
{
[unowned self] node,time in
if Int(node.position.y) < -self.blockHeight
{
node.removeFromParent()
self.addRandomBlocks1()
}
})
newBlock.run(SKAction.repeatForever(SKAction.group([move,addRandom])))
addChild(newBlock)
}
override func update(_ currentTime: CFTimeInterval) {
}
override func didFinishUpdate()
{
killNodes.forEach{$0.removeFromParent()}
}
func didBegin(_ contact: SKPhysicsContact) {
//This will organize the bodies so that the lowest category is A
let bodies = (contact.bodyA.categoryBitMask <= contact.bodyB.categoryBitMask) ? (A:contact.bodyA,B:contact.bodyB) : (A:contact.bodyB,B:contact.bodyA)
switch (bodies.A.categoryBitMask,bodies.B.categoryBitMask)
{
case let (a, b) where ((a & BodyType.player.rawValue) | (b & BodyType.sides.rawValue)) > 0:
killNodes.append(bodies.A.node!)
let label = SKLabelNode(text: "Gameover")
label.position = CGPoint(x:self.size.width/2,y:self.size.height/2)
addChild(label)
default:()
}
}
func didEnd(_ contact: SKPhysicsContact) {
//This will organize the bodies so that the lowest category is A
let bodies = (contact.bodyA.categoryBitMask <= contact.bodyB.categoryBitMask) ? (A:contact.bodyA,B:contact.bodyB) : (A:contact.bodyB,B:contact.bodyA)
switch (bodies.A.categoryBitMask,bodies.B.categoryBitMask)
{
case let (a, b) where ((a & BodyType.player.rawValue) | (b & BodyType.score.rawValue)) > 0:
currentScore += 1
run(playSound, withKey:"phaser")
scoreLabel.text = String(currentScore)
default:()
}
}
}