Here is the code I have now, did I update it correctly?

import SwiftUI
import Combine

struct ContentView: View {
 var body: some View {
 StartScreen()
 }
}

struct ContentView\_Previews: PreviewProvider {
 static var previews: some View {
 ContentView()
 }
}

struct StartScreen: View {
 @State private var showGameView = false

 var body: some View {
 VStack {
 Text("Arkanoid Clone")
 .font(.largeTitle)
 .bold()
 .padding()

 Button(action: {
 showGameView.toggle()
 }) {
 Text("Start")
 .font(.title)
 .padding()
 }
 .sheet(isPresented: $showGameView) {
 GameView(safeAreaInsets: safeAreaInsets)
 }
 }
 }
}

// GameViewModel.swift
class GameViewModel: ObservableObject {
 @Published var bricks: [Brick] = {
 var bricksArray = [Brick]()
 for i in 0..<6 \* 10 {
 bricksArray.append(Brick(id: i, hit: false))
 }
 return bricksArray
 }()
 @Published var ballPosition: CGPoint = CGPoint(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height - 100)
 @Published var paddlePosition: CGFloat = UIScreen.main.bounds.width / 2
 private var ballDirection: CGVector = CGVector(dx: 2, dy: -2)
 private var gameRunLoop: AnyCancellable?
 private let acceleration: CGFloat = 1.05
 private var safeAreaInsets: EdgeInsets
 
 private func isCollidingWithBrick(\_ brick: Brick) -> Bool {
 let brickWidth: CGFloat = 60
 let brickHeight: CGFloat = 20
 let ballRadius: CGFloat = 10

 let brickX = CGFloat(30 + (brick.id % 10) \* 65)
 let brickY = CGFloat(60 + (brick.id / 10) \* 30)

 let minX = brickX - brickWidth / 2 - ballRadius
 let maxX = brickX + brickWidth / 2 + ballRadius
 let minY = brickY - brickHeight / 2 - ballRadius
 let maxY = brickY + brickHeight / 2 + ballRadius

 return ballPosition.x >= minX && ballPosition.x <= maxX && ballPosition.y >= minY && ballPosition.y <= maxY
 }

 init(safeAreaInsets: EdgeInsets) {
 \_viewModel = StateObject(wrappedValue: GameViewModel(safeAreaInsets: safeAreaInsets))
 self.safeAreaInsets = safeAreaInsets
 let timer = Timer.publish(every: 0.01, on: .main, in: .common)
 gameRunLoop = timer.autoconnect().sink { [weak self] \_ in
 self?.updateGame()
 }
 }

 private func updateGame() {
 ballPosition = CGPoint(x: ballPosition.x + ballDirection.dx, y: ballPosition.y + ballDirection.dy)

 // Check for wall collisions
 if ballPosition.x <= 10 || ballPosition.x >= UIScreen.main.bounds.width - 10 {
 ballDirection.dx = -ballDirection.dx
 }

 if ballPosition.y <= 10 {
 ballDirection.dy = -ballDirection.dy
 }

 // Check for paddle collision
 if ballPosition.y >= UIScreen.main.bounds.height - safeAreaInsets.bottom - 70 &&
 ballPosition.x >= paddlePosition - 50 &&
 ballPosition.x <= paddlePosition + 50 {
 ballDirection.dy = -ballDirection.dy
 }
 // Check for brick collisions
 if let index = bricks.firstIndex(where: { !($0.hit) && isCollidingWithBrick($0) }) {
 bricks[index].hit = true
 collideWithBrick(at: index)
 }
 }

 func collideWithBrick(at index: Int) {
 ballDirection.dx \*= acceleration
 ballDirection.dy \*= acceleration
 ballDirection.dy = -ballDirection.dy
 }
}

struct Brick: Identifiable {
 var id: Int
 var hit: Bool
}
struct GameView: View {
 @GestureState private var dragOffset = CGSize.zero
 @StateObject private var viewModel: GameViewModel
 @State private var safeAreaInsets: EdgeInsets = EdgeInsets()
 @State private var bricks: [Brick] = {
 var bricksArray = [Brick]()
 for i in 0..<6 \* 10 {
 bricksArray.append(Brick(id: i, hit: false))
 }
 return bricksArray
 }()
 
 struct SafeAreaInsetsKey: PreferenceKey {
 static var defaultValue: EdgeInsets = EdgeInsets()

 static func reduce(value: inout EdgeInsets, nextValue: () -> EdgeInsets) {
 value = nextValue()
 }
 }

 var body: some View {
 GeometryReader { geometry in
 ZStack {
 Rectangle()
 .fill(Color.black)
 .edgesIgnoringSafeArea(.all)
 .background(GeometryReader { geometry in
 Color.clear.preference(key: SafeAreaInsetsKey.self, value: geometry.safeAreaInsets)
 })
 .onPreferenceChange(SafeAreaInsetsKey.self) { value in
 safeAreaInsets = value
 }

 Paddle(geometry: <#GeometryProxy#>)
 .frame(width: 100, height: 20)
 .position(x: viewModel.paddlePosition, y: geometry.size.height - 50 - geometry.safeAreaInsets.bottom)
 .gesture(
 DragGesture()
 .onChanged { value in
 let newPosition = viewModel.paddlePosition + value.translation.width
 viewModel.paddlePosition = min(max(newPosition, 50), UIScreen.main.bounds.width - 50)
 }
 )

 ForEach(viewModel.bricks) { brick in
 if !brick.hit {
 BrickView()
 .position(
 x: CGFloat(30 + (brick.id % 10) \* 65),
 y: CGFloat(60 + (brick.id / 10) \* 30)
 )
 }
 }

 Ball()
 .position(viewModel.ballPosition)
 }
 }
 }
}
struct Paddle: View {
 var geometry: GeometryProxy

 var body: some View {
 RoundedRectangle(cornerRadius: 10)
 .frame(width: 100, height: 20)
 .foregroundColor(.white)
 }
}
 struct Ball: View {
 var body: some View {
 Circle()
 .frame(width: 20, height: 20)
 .foregroundColor(.white)
 }
 }

struct BrickView: View {
 var body: some View {
 RoundedRectangle(cornerRadius: 5)
 .frame(width: 60, height: 20)
 .foregroundColor(.green)
 }
}
지금 가지고 있는 코드는 다음과 같습니다. 올바르게 업데이트했나요?import SwiftUIimport Combine구조체 ContentView: View { var body: 일부 View { StartScreen() }}구조체 ContentView\_Previews: PreviewProvider { static var previews: 일부 View { ContentView() }}구조체 StartScreen: View { @State private var showGameView = false var body: 일부 뷰 { VStack { Text("Arkanoid Clone") .font(.largeTitle) .bold() .padding() Button(action: { showGameView.toggle() }) { Text("시작") .font(.title) .padding() } .sheet(isPresented: $showGameView) { GameView(safeAreaInsets: safeAreaInsets) } } }}// GameViewModel.swift게임뷰모델 클래스: ObservableObject { 게시된 var bricks: [Brick] = { var bricksArray = [Brick]() for i in 0..<6 \* 10 { bricksArray.append(Brick(id: i, hit: false)) } 반환 bricksArray }() 게시된 var ballPosition: CGPoint = CGPoint(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height - 100) 게시된 변수 패들 포지션: CGFloat = UIScreen.main.bounds.width / 2 private var ballDirection: CGVector = CGVector(dx: 2, dy: -2) private var gameRunLoop: AnyCancellable? private let 가속도: CGFloat = 1.05 private var safeAreaInsets: EdgeInsets  private func isCollidingWithBrick(\_ brick: Brick) -> Bool { let brickWidth: CGFloat = 60 let brickHeight: CGFloat = 20 let ballRadius: CGFloat = 10 let brickX = CGFloat(30 + (brick.id % 10) \* 65) let brickY = CGFloat(60 + (brick.id / 10) \* 30) let minX = brickX - brickWidth / 2 - ballRadius let maxX = brickX + brickWidth / 2 + ballRadius let minY = brickY - brickHeight / 2 - ballRadius let maxY = brickY + brickHeight / 2 + ballRadius return ballPosition.x >= minX && ballPosition.x <= maxX && ballPosition.y >= minY && ballPosition.y <= maxY } init(safeAreaInsets: EdgeInsets) { \_viewModel = StateObject(wrappedValue: GameViewModel(safeAreaInsets: safeAreaInsets)) self.safeAreaInsets = safeAreaInsets let timer = Timer.publish(every: 0.01, on: .main, in: .common) gameRunLoop = timer.autoconnect().sink { [약한 self] \_ in self?.updateGame() } } private func updateGame() { ballPosition = CGPoint(x: ballPosition.x + ballDirection.dx, y: ballPosition.y + ballDirection.dy) // 벽 충돌 확인 if ballPosition.x <= 10 || ballPosition.x >= UIScreen.main.bounds.width - 10 { ballDirection.dx = -ballDirection.dx } if ballPosition.y <= 10 { ballDirection.dy = -ballDirection.dy } // 패들 충돌 확인 if ballPosition.y >= UIScreen.main.bounds.height - safeAreaInsets.bottom - 70 && ballPosition.x >= paddlePosition - 50 && ballPosition.x <= 패들위치 + 50 { ballDirection.dy = -ballDirection.dy } // 브릭 충돌 확인 if let index = bricks.firstIndex(where: { !($0.hit) && isCollidingWithBrick($0) }) { bricks[index].hit = true collideWithBrick(at: index) } } func collideWithBrick(at index: Int) { ballDirection.dx \*= 가속도 ballDirection.dy \*= 가속도 ballDirection.dy = -ballDirection.dy }}구조체 Brick: 식별 가능 { var id: Int var hit: Bool}구조체 GameView: View { @GestureState private var dragOffset = CGSize.0 상태 오브젝트 비공개 var viewModel: GameViewModel State private var safeAreaInsets: EdgeInsets = EdgeInsets() State private var bricks: [Brick] = { var bricksArray = [Brick]() for i in 0..<6 \* 10 { bricksArray.append(Brick(id: i, hit: false)) } 반환 bricksArray }()  구조체 SafeAreaInsetsKey: PreferenceKey { static var defaultValue: EdgeInsets = EdgeInsets() static func reduce(value: inout EdgeInsets, nextValue: () -> EdgeInsets) { value = nextValue() } } var body: some View { 지오메트리 리더 { 지오메트리 in ZStack { Rectangle() .fill(Color.black) .edgesIgnoringSafeArea(.all) .background(GeometryReader { 지오메트리 in Color.clear.preference(키: SafeAreaInsetsKey.self, 값: geometry.safeAreaInsets) }) .onPreferenceChange(SafeAreaInsetsKey.self) { 값 in safeAreaInsets = 값 } 패들(지오메트리: <#지오메트리프록시#>) .frame(너비: 100, 높이: 20) .position(x: viewModel.paddlePosition, y: geometry.size.height - 50 - geometry.safeAreaInsets.bottom) .gesture( 드래그 제스처() .onChanged { 값 in let newPosition = viewModel.paddlePosition + value.translation.width viewModel.paddlePosition = min(max(newPosition, 50), UIScreen.main.bounds.width - 50) } ) ForEach(viewModel.bricks) { brick in if !brick.hit { BrickView() .position( x: CGFloat(30 + (brick.id % 10) \* 65), y: CGFloat(60 + (brick.id / 10) \* 30) ) } } Ball() .position(viewModel.ballPosition) } } }}구조체 패들: View { var 지오메트리: GeometryProxy var body: 일부 View { RoundedRectangle(cornerRadius: 10) .frame(너비: 100, 높이: 20) .foregroundColor(.white) }} 구조체 Ball: View { var body: 일부 View { Circle() .frame(너비: 20, 높이: 20) .foregroundColor(.white) } }구조체 BrickView: View { var body: 일부 View { RoundedRectangle(cornerRadius: 5) .frame(너비: 60, 높이: 20) .