В настоящее время я разрабатываю пользовательский интерфейс для инфраструктуры, которую мне дали, которая играет в connect 4. Эта инфраструктура инкапсулирована в класс GameSession. Я не буду описывать тонкости его API и его работу. Я не верю, что это важно.
Я полагаю, что я неправильно понимаю очереди рассылки и неправильно их использую. Но я искал бесконечно и не нашел ничего, что указывало бы на решение моей проблемы.
Вот краткое объяснение происходящего. Метод, который контролирует ходы, это playGame (botStarts: Bool, atColumn: Int). В этом методе граница столкновения добавляется в правильной строке и столбце с помощью метода addBoundary (atRow: Int, atColumn: Int). Затем диск создается с помощью метода dropDisc (atColumn: Int, color: UIColor). Этот метод создает пользовательский UIView, добавляет его к представлению на экране и добавляет поведение при столкновении и гравитации. Он падает, пока не достигнет ранее добавленной границы.
В playGame () я сбрасываю диски на экран с помощью DispatchMain.Queue.async {dropDisc ()}. Но каждый раз, когда я вызываю playGame () во второй раз и далее, пользовательские диски рисуются в верхней части экрана, но они не падают. На первой итерации они рисуются и падают, как и ожидалось.
Ниже приведены функции, на которые я ссылался выше.
private func playGame(botStarts: Bool, dropPieceAt: Int) {
DispatchQueue.global(qos: .userInitiated).async {
if botStarts {
if let move = gameSession.move {
let column = move.action % self.gameSession.boardLayout.columns
let row = move.action / self.gameSession.boardLayout.columns
self.addBoundary(atRow: row, atColumn: column)
DispatchQueue.main.async {
self.dropDisc(atColumn: column, color: move.color)
}
}
} else {
let column = dropPieceAt
if self.gameSession.userPlay(at: column) {
if let move = self.gameSession.move {
print(move)
let column = move.action % self.gameSession.boardLayout.columns
let row = move.action / self.gameSession.boardLayout.columns
self.addBoundary(atRow: row, atColumn: column)
DispatchQueue.main.async {
self.dropDisc(atColumn: column, color: move.color)
}
}
if let move = self.gameSession.move {
let column = move.action % self.gameSession.boardLayout.columns
let row = move.action / self.gameSession.boardLayout.columns
self.addBoundary(atRow: row, atColumn: column)
DispatchQueue.main.async {
self.dropDisc(atColumn: column, color: move.color)
}
}
}
if self.gameSession.done {
if let outcome = self.gameSession.outcome {
DispatchQueue.main.async {
self.gameLabel.text = outcome.message + "\n Winning pieces \(outcome.winningPieces)"
}
}
}
}
}
}
private func dropDisc(atColumn: Int, color: UIColor) {
var frame = CGRect()
frame.origin = CGPoint.zero
frame.size = Constants.bubbleSize
let x = CGFloat(39) + CGFloat(47 * atColumn)
frame.origin.x = x
let bubbleView = DiscView(frame: frame, color: color)
gameView.addSubview(bubbleView)
collider.addItem(bubbleView)
gravity.addItem(bubbleView)
}
// Adds a boundary using the row and column obtained from game session.
private func addBoundary(atRow: Int, atColumn: Int) {
let fromCoordX = CGFloat(16 + (boardView.initialX-boardView.radius)) + CGFloat(47 * atColumn)
let toCoordX = fromCoordX + CGFloat(24)
let coordY = CGFloat(198.5 + (boardView.initialY+boardView.radius)) + CGFloat(45 * atRow)
let fromPoint = CGPoint(x: fromCoordX, y: coordY+1)
let toPoint = CGPoint(x: toCoordX, y: coordY+1)
self.collider.addBoundary(withIdentifier: "boundary" as NSCopying, from: fromPoint, to: toPoint)
self.drawLineFromPoint(start: fromPoint, toPoint: toPoint, ofColor: UIColor.red, inView: self.gameView)
}
Вот скриншот моего экрана: https://imgur.com/7M3fklo.
В нижнем ряду вы видите диск пользователя (желтый) и диск ботов (красный). Они были добавлены при первом вызове playGame (). Но сверху вы можете увидеть два диска, которые были добавлены при втором вызове playGame (). Они не падают.
Что бы я ни пытался
Любая обратная связь очень ценится!