SKAction & SKSpriteNode 麻烦



我正在使用 SKSprite 节点在 Swift 中创建一个纸牌游戏来显示卡面。

在我的"发牌">

功能中,它向每个玩家发 3 张牌,一次一张以"循环"方式发一张牌。这工作正常,但我正在尝试添加一些动画 - 我试图通过动画将其从牌组移动到玩家手牌位置来显示发给本地玩家的每张牌。

我可以让精灵节点在没有动画的情况下显示,但是当我尝试使用 SKAction 时,它在操作完成后给我以下错误:

原因:"试图添加已经具有父级的 SKNode:名称:"本地播放器节点"纹理:[ "CARD39" (203 x 350(] 位置:{281.25, 100.05000305175781}

class GameScene: SKScene {
let tempCard = SKSpriteNode(texture: SKTexture(imageNamed: "back"))
func deal() {
players = createPlayers(with: numberOfPlayers)

tempCard.setScale((screenSize.width/100) * 0.2)
tempCard.zPosition = 10
tempCard.name = "tempcard"
addChild(tempCard)

let localPlayer = 0
var i = 0
repeat {
print("Card number: (i)")
var x = 0
let xPos = screenSize.width * (0.25 * CGFloat(i+1))

players.forEach { player in

let newCard = self.deck.dealOneCard()
player.hand.addCard(card: newCard)

localPlayerNode = players[localPlayer].hand[i].cardImage()
localPlayerNode.position = CGPoint(x: xPos, y: screenSize.height * 0.15)
localPlayerNode.setScale((screenSize.width/100) * 0.2)
localPlayerNode.name = "local player node"

if player.id == localPlayer {

let moveCard = SKAction.move(to: CGPoint(x: xPos, y: screenSize.height * 0.15),duration: 1.5)

//addChild(localPlayerNode) --using this instead of SKAction works
tempCard.run(moveCard, completion: {() -> Void in
self.tempCard.removeFromParent()
self.addChild(self.localPlayerNode)
})
}
x+=1
}
i+=1
} while i<3

我相信问题在于在您的循环中添加播放器节点,然后不删除它们。我确定您不想每次调用" deal(("函数时都删除播放器,因此您应该在didMove((方法中添加播放器节点。 我已经整理了一个游乐场来演示这一点(github Link(.
我试图使用延迟来使牌一张一张地发牌,但这是一个不同的问题,你需要在其他地方寻找来解决。(带有 .run( 操作(的某些内容使其在循环完成之前实际上不会动画化。

像素艺术不佳的示例 GIF

class GameScene: SKScene {
let scale : CGFloat = 50
var deck : [String] = []
let composition = deckComp()
let numberOfPlayers = 3
var players : [Player] = []
override func didMove(to view: SKView) {
// creates deck
for c in deckComp().colors {
for s in deckComp().suits {
deck.append( s + " of " + c )
}
}
players = createPlayers(numberOfPlayers: numberOfPlayers, center : CGPoint(x : 25, y : 25))
// setup the scales, and players
for plyr in players {
plyr.setScale(scale: (frame.width/10000) * scale)
addChild( plyr.node)
}
}
func createPlayers(numberOfPlayers : Int, center : CGPoint) -> [Player] {
let radius = Float(5*scale)
let two_pi = 2 * 3.14159
let angular_positions = two_pi / Double(numberOfPlayers)
var players_out : [Player] = []
for i in 0...numberOfPlayers - 1 {
let sprite = SKSpriteNode(texture: SKTexture(imageNamed: "card_player.png"))
sprite.zPosition = 1
sprite.position = CGPoint( x : center.x + CGFloat(radius * sin( Float(angular_positions) * Float(i) )), y : center.y +  CGFloat(radius * cos( Float(angular_positions) * Float(i) )) )
sprite.texture?.filteringMode = .nearest // .linear for blurry, .nearest for pixely
let player_instance = Player(node : sprite, name : "Player " + String(i + 1), id : Int8(i + 1) )
players_out.append(player_instance)
}
return players_out
}
func deal() {
// I moved the setscale stuff for player sprites to didMove()
// first check if there is enough in deck
if deck.count > players.count {
var i = 0
repeat {
// add the temp card
let tempCard = SKSpriteNode(texture: SKTexture(imageNamed: "back"))
tempCard.size = CGSize( width: tempCard.size.width * (frame.width/10000) * scale, height : tempCard.size.height * (frame.width/10000) * scale )
tempCard.zPosition = 10
tempCard.texture?.filteringMode = .nearest
self.addChild(tempCard)
// done adding temporary card
let xPos = frame.width * (0.25 * CGFloat(i+1))
tempCard.position = CGPoint(x : xPos, y : 0.75 * frame.height)
let newCard = self.deck.popLast() // replaced dealOneCard() since I haven't defined it
players[i].addCard(card: newCard!)  // removed hand.addCard(), since I don't have the array extensions
//                player.name = "local player node"
let moveCard = SKAction.move(to: players[i].node.position ,duration: 1.5)
//addChild(localPlayerNode) --using this instead of SKAction works
tempCard.run(moveCard, completion: { () -> Void in tempCard.removeFromParent();                })
i += 1
} while i < players.count
} else { print("not enough cards to deal to everyone")} // when deck is empty
}
override func mouseUp(with event: NSEvent) {
deal()
}

最新更新