这是我从didMoveToScene调用的用于添加播放器的函数,我的场景固定在0.5、0.5处。 tileMapNode定位在0,-800处以使其在场景中居中,并且也锚定在0.5、0.5处。无论我将播放器放置在什么位置,它仍然是手机的死点。我在做什么错了。
func addPlayer() {
player = Player(imageNamed: GameConstants.StringConstants.playerImageName)
player.name = String(GameConstants.StringConstants.playerName)
player.anchorPoint = CGPoint(x: 0.5, y: 0.5)
player.position = CGPoint(x: (scene?.frame.midX)!, y: (scene?.frame.minY)!)
player.xScale = 1
player.yScale = 1
player.zPosition = GameConstants.ZPositions.playerZ
player.lightingBitMask = 1
PhysicsHelper.addPhysicsBody(to: player, with: GameConstants.StringConstants.playerName)
addAttackArea()
scene?.addChild(player)
lightsCameraAction()
player.playerState = .idle
}
这是完整的GameScene文件。我怎么知道场景何时加载?我是一个老派程序员。大约24年没有写任何代码了:)。情况有所改变。
import SpriteKit
//MARK:--------------------------Global Variables
enum GameState {
case playing, paused, finished
}
// MARK: ----------------------------------GameScene
class GameScene: SKScene, SKPhysicsContactDelegate {
// MARK: -----------------------------------Movement Variables
let movePointsPerSecond: CGFloat = 250.0
var velocity = CGVector(dx: 0.0, dy: 0.0)
var lastUpdateTime: CFTimeInterval = 0
// MARK: ----------------------------------Gesture Recognizer
let singleTapRec = UITapGestureRecognizer()
let lightNode: SKLightNode = SKLightNode()
let cameraNode: SKCameraNode = SKCameraNode()
let gameScene: SKScene = SKScene()
var gameState = GameState.playing {
willSet {
switch newValue {
case .playing:
player.playerState = .idle
case .finished:
player.playerState = .idle
case .paused:
scene?.isPaused = true
}
}
}
// MARK: ---------------------------------didMove to view
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
switch gameState {
case .playing:
setupGestures()
addPlayer()
addEnemy()
addEnemy()
addEnemy()
addEnemy()
addEnemy()
addEnemy()
case .paused:
scene?.isPaused = true
default:
break
}
}
// MARK: ---------------------Touches Section
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// var touchedLocation = CGPoint()
switch gameState {
case .playing:
//if let touch = touches.first {
//let touchLocation = touch.location(in: self)
// touchedLocation = touchLocation
player.playerState = .idle
// moveAndRotate(spriteNode: player, toPosition: touchedLocation)
// }
case .paused:
scene?.isPaused = true
default:
break
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
var touchedLocation = CGPoint()
switch gameState {
case .playing:
if let touch = touches.first {
let touchLocation = touch.location(in: self)
touchedLocation = touchLocation
player.playerState = .walking
moveAndRotate(spriteNode: player, toPosition: touchedLocation)
}
case .paused:
scene?.isPaused = true
default:
break
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
removeAllActions()
switch gameState {
case .playing:
player.playerState = .idle
player.removeAction(forKey: "RotateAction")
case .paused:
scene?.isPaused = true
default:
break
}
}
// MARK:------------------------------------Physics contact
func didBegin(_ contact: SKPhysicsContact) {
var enemyIndex = 0
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
if contact.bodyA.node?.name != "Player" && contact.bodyA.node?.name != "AttackArea" {
let node = contact.bodyA.node
enemyIndex = findEnemy(contactName: (node?.name)!)
} else {
let node = contact.bodyB.node
enemyIndex = findEnemy(contactName: (node?.name)!)
}
enemyID = enemyIndex
switch contactMask {
case GameConstants.PhysicsCategory.attackAreaCategory | GameConstants.PhysicsCategory.enemyCategory:
handleEnemyContact(entity: enemyIndex)
case GameConstants.PhysicsCategory.playerCategory | GameConstants.PhysicsCategory.enemyCategory:
handleEnemyContact(entity: enemyIndex)
default:
break
}
}
func didEnd(_ contact: SKPhysicsContact) {
}
// MARK: ---------------------Update Section
override func update(_ currentTime: CFTimeInterval) {
let deltaTime = max(1.0 / 30, currentTime - lastUpdateTime)
lastUpdateTime = currentTime
update(dt: deltaTime)
}
func update(dt: CFTimeInterval) {
if player.playerState == .walking {
let newX = player.position.x + velocity.dx * CGFloat(dt)
let newY = player.position.y + velocity.dy * CGFloat(dt)
player.position = CGPoint(x: newX, y: newY)
cameraNode.position = player.position
lightNode.position = player.position
newAttack.position = player.position
}
}
}
忘记添加游戏场景扩展。
import SpriteKit
// MARK: ----------------------------------Enumerations
enum Animation: String {
case Walking, Idle, Attacking, Waiting
}
enum RewardType: String {
case LevelUp, MagicItem, DefeatEnemy, DefeatBoss, CompleteQuest
}
enum Dice: Int {
case d20, d10, d8, d6, d4
}
// MARK: ----------------------------------GLobal Variables
var player: Player!
var enemy: Enemy!
let textureName: String = GameConstants.StringConstants.playerImageName
let playerTexture: SKTexture = SKTexture(imageNamed: GameConstants.StringConstants.playerImageName)
var playerPosition: CGPoint = CGPoint(x: 0, y: 0)
let attackAreaTexture: SKTexture = SKTexture(imageNamed: "AttackCircle")
var requiredXPForNextLevel = 0
let enemyTexture: SKTexture = SKTexture(imageNamed: GameConstants.StringConstants.enemyImageName)
var playerIsAttacking: Bool = false
var enemyIsAttacking: Bool = false
var playerIsDead: Bool = false
var enemyIsDead: Bool = false
var enemies: [Enemy] = []
var enemyID: Int = 0
var newAttack: SKSpriteNode!
extension GameScene {
//MARK:--------------------------------------------Add Player
func addPlayer() {
player = Player(imageNamed: GameConstants.StringConstants.playerImageName)
player.name = String(GameConstants.StringConstants.playerName)
player.anchorPoint = CGPoint(x: 0.5, y: 0.5)
player.position = CGPoint(x: 0, y: 0)
player.xScale = 1
player.yScale = 1
player.zPosition = GameConstants.ZPositions.playerZ
player.lightingBitMask = 1
PhysicsHelper.addPhysicsBody(to: player, with: GameConstants.StringConstants.playerName)
addAttackArea()
scene!.addChild(player)
lightsCameraAction()
player.playerState = .idle
}
//MARK:------------------------------------Lights and Camera
func lightsCameraAction() {
let lightNode: SKLightNode = setupLighting()
addChild(lightNode)
let cameraNode: SKCameraNode = setupCamera()
addChild(cameraNode)
}
//MARK:-------------------------------------------Add Enemy
func addEnemy() {
let enemyIndex = enemyID
enemy = Enemy(imageNamed: GameConstants.StringConstants.enemyImageName )
enemies.append(enemy)
let randomX = Int.random(in: -100 ..< 1500)
let randomY = Int.random(in: -100 ..< 1500)
let currentEnemy = enemies[enemyIndex]
currentEnemy.name = "Enemy\(enemyIndex + 1)"
currentEnemy.stats.id = enemyID
currentEnemy.position = CGPoint(x: randomX, y: randomY)
currentEnemy.xScale = 1
currentEnemy.yScale = 1
currentEnemy.zPosition = GameConstants.ZPositions.enemyZ
currentEnemy.lightingBitMask = 1
PhysicsHelper.addPhysicsBody(to: currentEnemy, with: GameConstants.StringConstants.enemyName)
addChild(currentEnemy)
enemyID += 1
}
//MARK:-------------------------------Attack
func addAttackArea() {
newAttack = SKSpriteNode(texture: attackAreaTexture, color: UIColor.clear, size: player.size)
newAttack.name = GameConstants.StringConstants.attackAreaName
newAttack.position = player.position
newAttack.size.width = player.size.width + 75
newAttack.size.height = player.size.height + 75
newAttack.zPosition = player.zPosition - 1
PhysicsHelper.addPhysicsBody(to: newAttack, with: GameConstants.StringConstants.attackAreaName)
addChild(newAttack)
}
func attack() {
player.playerState = .attacking
playerIsAttacking = true
if enemyIsDead {
playerIsAttacking = false
}
}
//MARK:----------------------------Gestures
func setupGestures() {
singleTapRec.addTarget(self, action: #selector(singleTap))
singleTapRec.numberOfTouchesRequired = 1
singleTapRec.numberOfTapsRequired = 1
view!.addGestureRecognizer(singleTapRec)
}
@objc func singleTap() {
attack()
}
func cleanUp() {
for gesture in (view?.gestureRecognizers)! {
view?.removeGestureRecognizer(gesture)
}
}
//MARK:-------------------------Lighting and Camera
func setupLighting() -> SKLightNode {
lightNode.lightColor = UIColor.white
lightNode.ambientColor = UIColor.black
lightNode.shadowColor = UIColor.black
lightNode.falloff = 1.5
lightNode.zPosition = GameConstants.ZPositions.objectZ
lightNode.alpha = 1
lightNode.position = player.position
return lightNode
}
func setupCamera() -> SKCameraNode {
camera = cameraNode
cameraNode.position = player.position
return cameraNode
}
//MARK:-----------------------------Handle Enemy Contact
func handleEnemyContact(entity: Int) {
//var currentEnemy = enemies[entity]
if enemies.count != 0 {
if enemies[entity].stats.hp <= 0 {
enemyIsDead = true
//handlePlayerReward(level: enemyLevel)
enemies[entity].removeFromParent()
enemies.remove(at: entity)
} else {
print("\nAttacking: \(enemies[entity].name as Any)")
print("enemyHP: \(enemies[entity].stats.hp)")
enemies[entity].stats.hp -= 1
}
}
}
//MARK:-------------------------------------Find Enemy
func findEnemy(contactName: String) -> Int {
var enemiesIndex = 0
var enemyIndex = 0
for _ in enemies {
let entityName = enemies[enemiesIndex].name
if entityName == contactName {
enemyIndex = enemiesIndex
enemies[enemyIndex].stats.id = enemyIndex
} else {
enemiesIndex += 1
}
}
return enemyIndex
}
//MARK:-------------------------------------Player Reward
func handlePlayerReward(level: Int) {
/*
let playerXP = userData?.value(forKey: "PlayerXP") as? Int
let newPlayerXP = (level * 10) + playerXP!
if newPlayerXP > requiredXPForNextLevel {
levelUp()
}
userData?["PlayerXP"] = newPlayerXP as Any
*/
}
//MARK:-----------------------------------------Level Up
func levelUp() {
/*
var enemyLevel = userData?.value(forKey: "\(enemyID)Level") as! Int
let playerXP = userData?.value(forKey: "PlayerXP") as! Int
let newPlayerXP = (enemyLevel * 10) + playerXP
enemyLevel += 1
userData?["P{layerXP"] = newPlayerXP
userData?["\(enemyID)Level"] = enemyLevel
requiredXPForNextLevel = requiredXPForNextLevel * 2
*/
}
//MARK-----------------------------------Roll Dice
func rollDice(die: Dice) -> Int {
switch die {
case .d20:
let d20 = Int(arc4random_uniform(20)) + 1
return d20
case .d10:
let d10 = Int(arc4random_uniform(10)) + 1
return d10
case .d8:
let d8 = Int(arc4random_uniform(8)) + 1
return d8
case .d6:
let d6 = Int(arc4random_uniform(6)) + 1
return d6
case .d4:
let d4 = Int(arc4random_uniform(4)) + 1
return d4
}
}
//MARK:-------------------------------Move and Rotate
func moveAndRotate(spriteNode: SKSpriteNode, toPosition position: CGPoint) {
let angle = atan2(position.y - spriteNode.position.y, position.x - spriteNode.position.x)
let rotateAction = SKAction.rotate(toAngle: angle + CGFloat.pi / 2, duration: 0, shortestUnitArc: true)
if let _ = spriteNode.action(forKey: "RotateAction") {
spriteNode.removeAction(forKey: "RotateAction")
spriteNode.run(rotateAction, withKey: "RotateAction")
} else {
spriteNode.run(rotateAction, withKey: "RotateAction")
}
let offsetX = position.x - spriteNode.position.x
let offsetY = position.y - spriteNode.position.y
let normal = simd_normalize(simd_double2(x: Double(offsetX), y: Double(offsetY)))
velocity = CGVector(dx: CGFloat(normal.x) * movePointsPerSecond, dy: CGFloat(normal.y) * movePointsPerSecond)
}
/*
func whoIsThis(entity: String) {
if entity != player.name! {
print("Entity: \(entity)")
print("EnemyID: \(enemyID)")
print("EnemyHP: \(String(describing: userData?.value(forKey: "HP")))")
print("EnemyName: \(String(describing: enemy.name))")
} else {
print("Entity: \(entity)")
print("PlayerHP: \(String(describing: userData?.value(forKey: "HP")))")
print("PlayerName: \(String(describing: player.name))")
}
}
*/
}
答案 0 :(得分:1)
如果我正确地遵循您的代码,则可能是由于您在更新循环中将相机居中放在播放器上。
如果您希望他位于屏幕底部,则将要偏移此位置,而不要将其直接设置在玩家的位置上,否则无论您将他移动到哪里,他都将始终居中。
//cameraNode.position = player.position
let yOffset = player.position.y+scene.height/2-player.size.height/2
cameraNode.position = CGPoint(player.position.x, yOffset) //might get you want you want.