1

I am creating a scorekeeper for board games. I have created numbered buttons that are supposed to increment my score by the number on the buttons. However, when the buttons are pressed no action occurs. When I set up a break point I can tell the button is being called, but no action is occurring - even when I put in basic elements such as changing my player name. Can you help me get the button to increment the "score" by the number displayed on the button.

struct ContentView: View {
@EnvironmentObject var theGame:Game
@ObservedObject var player1: Player
@ObservedObject var player2: Player
@ObservedObject var player3: Player
@ObservedObject var player4: Player
@State var isPlayer1Active: Bool = false
@State var isPlayer2Active: Bool = false
@State var isPlayer3Active: Bool = false
@State var isPlayer4Active: Bool = false

var body: some View {
    VStack {
        AdBannerView()
        HStack{
            VStack{
                Spacer()
                HStack{
                    VStack{
                        Button(action:{
                            player1.isPlayerActive = true
                            player2.isPlayerActive = false
                            player3.isPlayerActive = false
                            player4.isPlayerActive = false
                            theGame.activePlayer = player1.playerName
                        }){
                            PlayerView(player: player1)
                        }
                        Button(action:{
                            player1.isPlayerActive = false
                            player2.isPlayerActive = true
                            player3.isPlayerActive = false
                            player4.isPlayerActive = false
                            theGame.activePlayer = player2.playerName
                        }){
                            PlayerView(player: player2)
                        }
                        
                    }
                    VStack{
                        Button(action:{
                            player1.isPlayerActive = false
                            player2.isPlayerActive = false
                            player3.isPlayerActive = true
                            player4.isPlayerActive = false
                            theGame.activePlayer = player3.playerName
                            
                        }){
                                
                            PlayerView(player: player3)
                            
                        }
                        Button(action:{
                            player1.isPlayerActive = false
                            player2.isPlayerActive = false
                            player3.isPlayerActive = false
                            player4.isPlayerActive = true
                            theGame.activePlayer = player4.playerName
                            
                        }){
                            PlayerView(player: player4)
                        }
                        
                    }

                    addPointsCombinedView(player1: Player(), player2: Player(),player3: Player(), player4: Player())
                        .padding()
                        .layoutPriority(1)
                }
                .padding()
            }
        }
    }
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
    ContentView(player1: Player(), player2: Player(),player3: Player(), player4: Player())
        .environmentObject(Game(numberOfPlayers: 4))
        .previewDevice("iPad Pro (9.7-inch)")
}
}

PlayerView

struct PlayerView: View {
@ObservedObject var player: Player
@EnvironmentObject var theGame:Game;
@State var changeName: Bool = false

var borderSize: CGFloat = 2
var body: some View {
    
    HStack{
        Text(player.playerName)
            .foregroundColor(.white)
            .padding()
        VStack{
            Text("Score")
            Text(player.formattedScore)
        }
        .foregroundColor(.white)
        .padding()
        
    }
    .background(player.isPlayerActive ? Color.blue : Color.green)
    .cornerRadius(25)
    
    
    
    
    
}

}

/* Extension that allows custom corner radius for each corner.  This code was created by Mojtaba Hosseini and found on StackOverflow https://stackoverflow.com/questions/56760335/round-specific-corners-swiftui*/

/*    extension View {
func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
    clipShape(playerRoundedCornerView(radius: radius, corners: corners) )
}
}*/
/*This code was created by Mojtaba Hosseini and found on StackOverflow     https://stackoverflow.com/questions/56760335/round-specific-corners-swiftui*/
struct playerRoundedCornerView: Shape {

var radius: CGFloat = .infinity
var corners: UIRectCorner = .allCorners

func path(in rect: CGRect) -> Path {
    let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii:   CGSize(width: radius, height: radius))
    return Path(path.cgPath)
}
}
struct PlayerView_Previews: PreviewProvider {
static var previews: some View {
    PlayerView(player: Player())
}
}

AddScore Button

struct addScoreButton: View {
@ObservedObject var player1: Player
@ObservedObject var player2: Player
@ObservedObject var player3: Player
@ObservedObject var player4: Player
@EnvironmentObject var theGame:Game

var numberToAdd:String
var body: some View {
    Button(action: {
            player1.changePlayerName(newPlayerName: "Hello2")
        switch theGame.activePlayer{
        case player1.playerName:
            player1.addToScore(pointToAdd: addScore(numberToAdd: numberToAdd))
            
        case player2.playerName:
            player2.addToScore(pointToAdd: addScore(numberToAdd: numberToAdd))
        default:
            theGame.activePlayer = "hello world"
        }}){
    ZStack{
        Rectangle()
            .fill(Color.gray)
            //.frame(width: 75, height: 75, alignment: .center)
            .frame(minWidth: 70, idealWidth: 75, maxWidth: 100, minHeight: 70, idealHeight: 75, maxHeight: 100, alignment: .center)
            .padding(.bottom, 5)
            
        
        Text("\(numberToAdd)")
            .foregroundColor(.white)
            .bold()
            .font(.title)
            
    }

}

}

}
struct addScoreButton_Previews: PreviewProvider {
static var previews: some View {
    addScoreButton(player1: Player(), player2: Player(),player3: Player(), player4: Player(),numberToAdd: "+1")
}
}

func addScore(numberToAdd:String) -> Int {
    switch numberToAdd {
    case "+1":
        return 1
    case "+2":
        return 2
    case "+3":
        return 3
    case "+4":
        return 4
    case "+5":
        return 5
    case "+6":
        return 6
    case "+12":
        return 12
    case "-1":
        return -1
    case "-2":
        return -2
    default:
        return -3
    }
}

Combined View of the buttons:

struct addPointsCombinedView: View {
@ObservedObject var player1: Player
@ObservedObject var player2: Player
@ObservedObject var player3: Player
@ObservedObject var player4: Player
@EnvironmentObject var theGame:Game
var one:String = "+1"
var two:String = "+2"
var three:String = "+3"
var four:String = "+4"
var five:String = "+5"
var six:String = "+6"
var twelve:String = "+12"
var negOne:String = "-1"
var negTwo:String = "-2"


var body: some View {
    HStack {
        VStack{
            addScoreButton(player1: player1, player2: player2,player3: player3, player4: player4, numberToAdd: one)
            addScoreButton(player1: player1, player2: player2,player3: player3, player4: player4,numberToAdd: four)
            addScoreButton(player1: player1, player2: player2,player3: player3, player4: player4,numberToAdd: twelve)
            
        }
        .padding(.trailing, 3)
        VStack{
            addScoreButton(player1: player1, player2: player2,player3: player3, player4: player4,numberToAdd: two)
            addScoreButton(player1: player1, player2: player2,player3: player3, player4: player4,numberToAdd: five)
            addScoreButton(player1: player1, player2: player2,player3: player3, player4: player4,numberToAdd: negOne)

        }
        VStack{
            addScoreButton(player1: player1, player2: player2,player3: player3, player4: player4,numberToAdd: three)
            addScoreButton(player1: player1, player2: player2,player3: player3, player4: player4,numberToAdd: six)
            addScoreButton(player1: player1, player2: player2,player3: player3, player4: player4,numberToAdd: negTwo)
        }
        .padding(.leading, 3)
    }
    
}
}

struct addPointsCombinedView_Previews: PreviewProvider {
static var previews: some View {
    addPointsCombinedView(player1: Player(), player2: Player(),player3: Player(), player4: Player())
}
}

PlayerObject:

class Player:ObservableObject {
@Published var playerName:String
@Published var score:[GameRound] = []
@Published var isPlayerPlayingThisGame:Bool
@Published var isPlayerActive:Bool
@Published var currentScore: Int
var formattedScore:String{
    String(currentScore)
}

//@Published let currentRound:Int
//@Published var beginningScore:Int
//@Published var endScore:Int
//@Published var pointsThisRound:[Int]


init(){
    playerName = "Player1"
    let newGame = GameRound(newRound: 1,beginningScore: 0 )
    isPlayerActive = false
    isPlayerPlayingThisGame = false
    currentScore = 0
    score.append(newGame)
    
}
func changePlayerName(newPlayerName: String){
    playerName = newPlayerName
}
/*adds the new points to the array of points made this round
and adds them to the current score */
func addToScore(pointToAdd: Int){
    //score.last?.addScore(pointsToAdd: pointToAdd)
    self.currentScore += pointToAdd
    score.last?.endScore += pointToAdd
    score.last?.pointsThisRound.append(pointToAdd)
    
}

/*starts a new round of the game*/
func newRound(){
    let newRound = GameRound(newRound:self.score.last!.currentRound+1,beginningScore: self.score.last!.endScore)
    self.score.append(newRound)
}
}

GameRoundObject

class GameRound{
let currentRound:Int
var beginningScore:Int
var endScore:Int
var pointsThisRound:[Int]
var scoreAsString:String{String(endScore)}

init(newRound:Int, beginningScore: Int){
    self.currentRound = newRound
    self.beginningScore = beginningScore
    self.endScore = newRound
    self.pointsThisRound = [0]
}

func addScore(pointsToAdd:Int){
    self.endScore += pointsToAdd
    self.pointsThisRound.append(pointsToAdd)
}

func roundAsString()->String{
    var roundNumber:String
    var round = "Round:"
    roundNumber = "\(self.currentRound)"
    round += roundNumber
    return round
}

}

Game Object

class Game:ObservableObject{
@Published var player1 = Player()
@Published var player2 = Player()
@Published var player3 = Player()
@Published var player4 = Player()
@Published var activePlayer:String
@Published var game:[Player] = []
@Published var currerntRound: Int

init(numberOfPlayers: Int){
    activePlayer = " "
    currerntRound = 1
    for i in 1...numberOfPlayers{
        switch i {
        case 1:
            game.append(player1)
            player1.isPlayerPlayingThisGame = true
        case 2:
            game.append(player2)
            player2.isPlayerPlayingThisGame = true
        case 3:
            game.append(player3)
            player3.isPlayerPlayingThisGame = true
        case 4:
            game.append(player4)
            player4.isPlayerPlayingThisGame = true
        default:
            break
        }
    }
}


}
Alemastr
  • 25
  • 3

1 Answers1

0

You currently have a line where you're creating new Player instances instead of referencing the already created ones.

Your line:

addPointsCombinedView(player1: Player(), player2: Player(),player3: Player(), player4: Player())

Should be:

addPointsCombinedView(player1: player1, player2: player2,player3: player3, player4: player4)

The above will solve your problem. However, on a general note, I'll also say that architecturally, I'm not sure it makes sense to store all of the players in Game environment variable that gets sent to every view and pass each player as an @ObservableObject parameter as well.

jnpdx
  • 45,847
  • 6
  • 64
  • 94
  • This worked thanks. You are right about the Game environment object. Frankly that was old code I need to clean up I was just trying something new. On another note - is there a way for me to make this answered so I can give you credit? – Alemastr Mar 15 '21 at 15:40
  • There is. You can click the green check mark to accept and the up arrow to mark it as helpful. Thanks! – jnpdx Mar 15 '21 at 15:55