我收到错误消息'使用未解析的标识符'在一个功能里面。我检查了我的目标成员资格,尝试重新输入func中的所有内容,检查了我的所有拼写,并重新创建了我遇到问题的GameScene.swift文件。请参阅附图以获取代码参考...
导入SpriteKit 导入CoreMotion
类GameScene:SKScene,SKPhysicsContactDelegate {
// Private GameScene Properties
var tapQueue = [Int]()
var contactQueue = [SKPhysicsContact]()
let motionManager: CMMotionManager = CMMotionManager()
var contentCreated = false
var invaderMovementDirection: InvaderMovementDirection = .Right
var timeOfLastMove: CFTimeInterval = 0.0
let timePerMove: CFTimeInterval = 1.0
var score: Int = 0
var shipHealth: Float = 1.0
enum InvaderMovementDirection {
case Right
case Left
case DownThenRight
case DownThenLeft
case None
}
enum InvaderType {
case A
case B
case C
static var size: CGSize {
return CGSize(width: 24, height: 16)
}
static var name: String {
return "invader"
}
}
enum BulletType {
case ShipFired
case InvaderFired
}
let kInvaderGridSpacing = CGSize(width: 12, height:12)
let kInvaderRowCount = 6
let kInvaderColCount = 6
let kShipSize = CGSize(width: 30, height: 16)
let kShipName = "ship"
let kScoreHudName = "scoreHud"
let kHealthHudName = "healthHud"
let kShipFiredBulletName = "shipFiredBullet"
let kInvaderFiredBulletName = "invaderFiredBullet"
let kBulletSize = CGSize(width:4, height: 8)
let kInvaderCategory: UInt32 = 0x1 << 0
let kShipFiredBulletCategory: UInt32 = 0x1 << 1
let kShipCategory: UInt32 = 0x1 << 2
let kSceneEdgeCategory: UInt32 = 0x1 << 3
let kInvaderFiredBulletCategory: UInt32 = 0x1 << 4
// Scene Setup and Content Creation
override func didMoveToView(view: SKView) {
if (!self.contentCreated) {
self.createContent()
self.contentCreated = true
motionManager.startAccelerometerUpdates()
physicsWorld.contactDelegate = self
}
}
func createContent() {
let invader = SKSpriteNode(imageNamed: "InvaderA_00.png")
invader.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
// self.addChild(invader)
physicsBody = SKPhysicsBody(edgeLoopFromRect: frame)
physicsBody!.categoryBitMask = kSceneEdgeCategory
setupInvaders()
setupShip()
setupHud()
// black space color
self.backgroundColor = SKColor.blackColor()
}
func loadInvaderTexturesOfType(invaderType: InvaderType) -> [SKTexture] {
var prefix: String
switch(invaderType) {
case .A:
prefix = "InvaderA"
case .B:
prefix = "InvaderB"
case .C:
prefix = "InvaderC"
}
return [SKTexture(imageNamed: String(format: "%@_00.png", prefix)),
SKTexture(imageNamed: String(format: "%@_01.png", prefix))]
}
func makeInvaderOfType(invaderType: InvaderType) -> SKNode {
let invaderTextures = loadInvaderTexturesOfType(invaderType)
let invader = SKSpriteNode(texture: invaderTextures[0])
invader.name = InvaderType.name
invader.runAction(SKAction.repeatActionForever(SKAction.animateWithTextures(invaderTextures, timePerFrame: timePerMove)))
invader.physicsBody = SKPhysicsBody(rectangleOfSize: invader.frame.size)
invader.physicsBody!.dynamic = false
invader.physicsBody!.categoryBitMask = kInvaderCategory
invader.physicsBody!.contactTestBitMask = 0x0
invader.physicsBody!.collisionBitMask = 0x0
return invader
}
func setupInvaders() {
let baseOrigin = CGPoint(x: size.width / 3, y: size.height / 2)
for row in 0..<kInvaderRowCount {
var invaderType: InvaderType
if row % 3 == 0 {
invaderType = .A
} else if row % 3 == 1 {
invaderType = .B
} else {
invaderType = .C
}
let invaderPositionY = CGFloat(row) * (InvaderType.size.height * 2) + baseOrigin.y
var invaderPosition = CGPoint(x: baseOrigin.x, y: invaderPositionY)
for _ in 1..<kInvaderRowCount {
let invader = makeInvaderOfType(invaderType)
invader.position = invaderPosition
addChild(invader)
invaderPosition = CGPoint(
x: invaderPosition.x + InvaderType.size.width + kInvaderGridSpacing.width,
y: invaderPositionY
)
}
}
}
func setupShip() {
let ship = makeShip()
ship.position = CGPoint(x: size.width / 2.0, y: kShipSize.height / 2.0)
addChild(ship)
}
func makeShip() -> SKNode {
let ship = SKSpriteNode(color: SKColor.greenColor(), size: kShipSize)
ship.name = kShipName
ship.physicsBody = SKPhysicsBody(rectangleOfSize: ship.frame.size)
ship.physicsBody!.dynamic = true
ship.physicsBody!.affectedByGravity = false
ship.physicsBody!.mass = 0.02
ship.physicsBody!.categoryBitMask = kShipCategory
ship.physicsBody!.contactTestBitMask = 0x0
ship.physicsBody!.collisionBitMask = kSceneEdgeCategory
return ship
}
func setupHud() {
let scoreLabel = SKLabelNode(fontNamed: "Courier")
scoreLabel.name = kScoreHudName
scoreLabel.fontSize = 25
scoreLabel.fontColor = SKColor.greenColor()
scoreLabel.text = String(format: "Score: %04u", 0)
scoreLabel.position = CGPoint(
x: frame.size.width / 2,
y: size.height - (40 + scoreLabel.frame.size.height/2)
)
addChild(scoreLabel)
let healthLabel = SKLabelNode(fontNamed: "Courier")
healthLabel.name = kHealthHudName
healthLabel.fontSize = 25
healthLabel.fontColor = SKColor.redColor()
healthLabel.text = String(format: "Health: %.1f%%", shipHealth * 100.0)
healthLabel.position = CGPoint(
x: frame.size.width / 2,
y: size.height - (80 + healthLabel.frame.size.height/2)
)
addChild(healthLabel)
func adjustScoreBy(points: Int) {
score += points
if let score = childNodeWithName(kScoreHudName) as? SKLabelNode {
score.text = String(format: "Score: %04u", self.score)
}
}
func adjustShipHealthBy(healthAdjustment: Float) {
shipHealth = max(shipHealth + healthAdjustment, 0)
if let health = childNodeWithName(kHealthHudName) as? SKLabelNode {
health.text = String(format: "Health: %.1f%%", self.shipHealth * 100)
}
}
}
func makeBulletOfType(bulletType: BulletType) -> SKNode {
var bullet: SKNode
switch bulletType {
case .ShipFired:
bullet = SKSpriteNode(color: SKColor.greenColor(), size: kBulletSize)
bullet.name = kShipFiredBulletName
bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.frame.size)
bullet.physicsBody!.dynamic = true
bullet.physicsBody!.affectedByGravity = false
bullet.physicsBody!.categoryBitMask = kShipFiredBulletCategory
bullet.physicsBody!.contactTestBitMask = kInvaderCategory
bullet.physicsBody!.collisionBitMask = 0x0
case .InvaderFired:
bullet = SKSpriteNode(color: SKColor.magentaColor(), size: kBulletSize)
bullet.name = kInvaderFiredBulletName
bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.frame.size)
bullet.physicsBody!.dynamic = true
bullet.physicsBody!.affectedByGravity = false
bullet.physicsBody!.categoryBitMask = kInvaderFiredBulletCategory
bullet.physicsBody!.contactTestBitMask = kShipCategory
bullet.physicsBody!.collisionBitMask = 0x0
break
}
return bullet
}
// Scene Update
func moveInvadersForUpdate(currentTime: CFTimeInterval) {
if (currentTime - timeOfLastMove < timePerMove) {
return
}
determineInvaderMovementDirection()
enumerateChildNodesWithName(InvaderType.name) {
node, stop in
switch self.invaderMovementDirection {
case .Right:
node.position = CGPointMake(node.position.x + 10, node.position.y)
case .Left:
node.position = CGPointMake(node.position.x - 10, node.position.y)
case .DownThenLeft, .DownThenRight:
node.position = CGPointMake(node.position.x, node.position.y - 10)
case .None:
break
}
self.timeOfLastMove = currentTime
}
}
func processUserMotionForUpdate(currentTime: CFTimeInterval) {
if let ship = childNodeWithName(kShipName) as? SKSpriteNode {
if let data = motionManager.accelerometerData {
if fabs(data.acceleration.x) > 0.2 {
// This is how ship moves
ship.physicsBody!.applyForce(CGVectorMake(40.0 * CGFloat(data.acceleration.x), 0))
}
}
}
}
func fireInvaderBulletsForUpdate(currentTime: CFTimeInterval) {
let existingBullet = childNodeWithName(kInvaderFiredBulletName)
if existingBullet == nil {
var allInvaders = Array<SKNode>()
enumerateChildNodesWithName(InvaderType.name) {
node, stop in
allInvaders.append(node)
}
if allInvaders.count > 0 {
let allInvadersIndex = Int(arc4random_uniform(UInt32(allInvaders.count)))
let invader = allInvaders[allInvadersIndex]
let bullet = makeBulletOfType(.InvaderFired)
bullet.position = CGPoint(
x: invader.position.x,
y: invader.position.y - invader.frame.size.height / 2 + bullet.frame.size.height / 2
)
let bulletDestination = CGPoint(x: invader.position.x, y: -(bullet.frame.size.height / 2))
fireBullet(bullet, toDestination: bulletDestination, withDuration: 2.0, andSoundFileName: "InvaderBullet.wav")
}
}
}
func processContactsForUpdate(currentTime: CFTimeInterval) {
for contact in contactQueue {
handleContact(contact)
if let index = contactQueue.indexOf(contact) {
contactQueue.removeAtIndex(index)
}
}
}
override func update(currentTime: CFTimeInterval) {
processContactsForUpdate(currentTime)
processUserTapsForUpdate(currentTime)
processUserMotionForUpdate(currentTime)
moveInvadersForUpdate(currentTime)
fireInvaderBulletsForUpdate(currentTime)
}
// Scene Update Helpers
func processUserTapsForUpdate(currentTime: CFTimeInterval) {
for tapCount in tapQueue {
if tapCount == 1 {
fireShipBullets()
}
tapQueue.removeAtIndex(0)
}
}
// Invader Movement Helpers
func determineInvaderMovementDirection() {
var proposedMovementDirection: InvaderMovementDirection = invaderMovementDirection
enumerateChildNodesWithName(InvaderType.name) {
node, stop in
switch self.invaderMovementDirection {
case .Right:
if (CGRectGetMaxX(node.frame) >= node.scene!.size.width - 1.0) {
proposedMovementDirection = .DownThenLeft
stop.memory = true
}
case .Left:
if (CGRectGetMinX(node.frame) <= 1.0) {
proposedMovementDirection = .DownThenRight
stop.memory = true
}
case .DownThenLeft:
proposedMovementDirection = .Left
stop.memory = true
case .DownThenRight:
proposedMovementDirection = .Right
stop.memory = true
default:
break
}
}
if (proposedMovementDirection != invaderMovementDirection) {
invaderMovementDirection = proposedMovementDirection
}
}
// Bullet Helpers
func fireBullet(bullet: SKNode, toDestination destination: CGPoint, withDuration duration: CFTimeInterval, andSoundFileName soundName: String) {
let bulletAction = SKAction.sequence([
SKAction.moveTo(destination, duration: duration),
SKAction.waitForDuration(3.0 / 60.0), SKAction.removeFromParent()
])
let soundAction = SKAction.playSoundFileNamed(soundName, waitForCompletion: true)
bullet.runAction(SKAction.group([bulletAction, soundAction]))
addChild(bullet)
}
func fireShipBullets() {
let existingBullet = childNodeWithName(kShipFiredBulletName)
if existingBullet == nil {
if let ship = childNodeWithName(kShipName) {
let bullet = makeBulletOfType(.ShipFired)
bullet.position = CGPoint(
x: ship.position.x,
y: ship.position.y + ship.frame.size.height - bullet.frame.size.height / 2
)
let bulletDestination = CGPoint(
x: ship.position.x,
y: frame.size.height + bullet.frame.size.height / 2
)
fireBullet(bullet, toDestination: bulletDestination, withDuration: 1.0, andSoundFileName: "ShipBullet.wav")
}
}
}
// User Tap Helpers
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let touch = touches.first {
if (touch.tapCount == 1) {
tapQueue.append(1)
}
}
}
// Physics Contact Helpers
func didBeginContact(contact: SKPhysicsContact) {
contactQueue.append(contact)
}
func handleContact(contact: SKPhysicsContact) {
if contact.bodyA.node?.parent == nil || contact.bodyB.node?.parent == nil {
return
}
let nodeNames = [contact.bodyA.node!.name!, contact.bodyB.node!.name!]
if nodeNames.contains(kShipName) && nodeNames.contains(kInvaderFiredBulletName) {
runAction(SKAction.playSoundFileNamed("SHipHit.wav", waitForCompletion: false))
adjustShipHealthBy(-0.334)
if shipHealth <= 0.0 {
contact.bodyA.node!.removeFromParent()
contact.bodyB.node!.removeFromParent()
} else {
if let ship = self.childNodeWithName(kShipName) {
ship.alpha = CGFloat(shipHealth)
if contact.bodyA.node == ship {
contact.bodyB.node!.removeFromParent()
}
}
}
} else if nodeNames.contains(InvaderType.name) && nodeNames.contains(kShipFiredBulletName) {
runAction(SKAction.playSoundFileNamed("InvaderHit.wav", waitForCompletion: false))
contact.bodyA.node!.removeFromParent()
contact.bodyB.node!.removeFromParent()
adjustScoreBy(100)
}
}
答案 0 :(得分:1)
问题是adjustScoreBy
/ adjustShipHealthBy
是在handleContact
不可见的地方宣布的。它们是另一种方法的内部吗?私有超级?完全是一个单独模块的一部分?这可能发生的原因有很多,如果adjustScoreBy
的范围不包括handleContact
,为什么不能立即明白,那么您需要在此处发布完整的上下文。
更新:看看,我的第一个猜测是正确的!这两个函数确实是另一个方法的内部函数,特别是setupHud
。将它们移到该功能之外,然后调用它们就没问题了。