어떻게 swiftUI를 사용하여 탈출 게임 제2부분을 만듭니까

51924 단어 gamedeviosswiftuiswift

창의 항목


다음으로 우리는 게임 중의 물품의 생명 주기를 고려한다.이것은 표준적이다.본문 제1부분에서 소개한 빠른 치부 방법을 참고합시다.
창에 존재하는 항목을 클릭하면 이 항목은 창에서 사라지고 프로젝트 연결에 들어갑니다. 이것은 단독 구성 요소입니다.
다른 곳에서 이 항목을 사용하고 싶을 때, dock의 항목을 눌러서 선택할 수 있습니다.
다음에 화면에 존재하는 항목을 배치하기 위해 보기가 필요합니다.이것이 바로 WindowTool입니다.날래다
WindowTool.swift

import SwiftUI

struct WindowTool: View {

    @State var putItem : Tool
    @State var Width : CGFloat
    @State var Height : CGFloat
    @State var X : CGFloat
    @State var Y : CGFloat

    var body: some View {
        if !itemData.itemArray.contains(putItem) && !putItem.isTaken {
            {
                Image(putItem.image).resizable()
            }()
            .frame(minWidth: 0 ,maxWidth: Width, minHeight: 0 ,maxHeight: Height)
            .offset(x: X, y: Y) 
            .onTapGesture {
                putItem.isTaken = true
                addItem(item: putItem)
                print(itemData.itemArray)
            }
        } else {

        }
    }
    // to add an item
    func addItem(item: Tool) {
        itemData.itemArray.append(item)
    }

}
우리는 생명 주기의 연장을 고려할 것이다.한 항목을 클릭하면 우리는 어떻게 해야 합니까?
여기서 우리는 프로젝트 정지점을 만들고 장면을 만들고 이 장면에서 프로젝트가 클릭한 후에 정지점에 들어가려고 한다.
현재 우리는 물품의 회수 순서에 대해 어떠한 제한도 하지 않는다.여기서 기본 그룹을 사용하자.프로젝트 대상의 끝에 빈 도구 형식 그룹을 만들었습니다.
코드입니다.dock 측 코드는 ForEach 구문을 사용합니다.
itemDock.swift

import SwiftUI

struct ItemDock: View {


    var body: some View {
        ZStack{
            Rectangle()
                .fill(Color.blue.opacity(0.3))
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 50, maxHeight: 70)
            HStack(spacing: 5){
                ForEach(0 ..< itemData.itemArray.count, id: \.self) { index in
                    {
                        Image(itemData.itemArray[index].image).resizable()
                            .frame(minWidth: 0 ,maxWidth: 50, minHeight: 0 ,maxHeight: 50, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
                            .background(Color.white)
                            .overlay(
                                Rectangle()
                                    .stroke(itemData.itemArray[index].isSelected ?  Color.red : Color.clear, lineWidth: 5)
                            )
                    }().onTapGesture {
                        itemData.itemArray[index].isSelected.toggle()
                        itemData.itemArray[index].isTaken = true

                    }
                }
            }
        }
    }
}
item 대상이 아직 존재하지 않기 때문에 테스트할 수 없지만, 어떻게 계속할지 찾아보겠습니다.
클릭하면 항목의 isTaken 로고가 선택되고 항목이 창에서 사라지며 옆에 있는 dock에 놓입니다.
dock의 항목을 눌렀을 때, 항목마다 isSelected 로고가 선택되고, 프레임이 빨간색으로 변합니다.
이 곳에서 프로젝트의 대상을 만듭니다.
ItemObject.swift

import Foundation


struct Tool : Equatable, Identifiable {
    let id : Int
    var text: String
    var image: String
    var isTaken: Bool
    var isSelected: Bool
}


class ItemObject: ObservableObject {
    // for singleton
    static let shared = ItemObject()
    private init(){}

    @Published var item1 = Tool(id: 1, text: "This is item 1", image: "item1.png", isTaken: false, isSelected: false)
    @Published var item2 = Tool(id: 2, text: "This is item 2", image: "item2.png", isTaken: false, isSelected: false)
    @Published var item3 = Tool(id: 3, text: "This is item 3", image: "item3.png", isTaken: false, isSelected: false)
    @Published var item4 = Tool(id: 4, text: "This is item 4", image: "item4.png", isTaken: false, isSelected: false)
    @Published var item5 = Tool(id: 5, text: "This is item 5", image: "item5.png", isTaken: false, isSelected: false)
    @Published var item6 = Tool(id: 6, text: "This is item 6", image: "item6.png", isTaken: false, isSelected: false)
    @Published var item7 = Tool(id: 7, text: "This is item 7", image: "item7.png", isTaken: false, isSelected: false)
    @Published var item8 = Tool(id: 8, text: "This is item 8", image: "item8.png", isTaken: false, isSelected: false)
    @Published var item9 = Tool(id: 9, text: "This is item 9", image: "item9.png", isTaken: false, isSelected: false)

    // empty arrays
    @Published var itemArray: [Tool] = []



}

새로 만든 WindowTool에 추가해야 합니다.
WindowTool.swift

import SwiftUI

struct WindowTool: View {

    @EnvironmentObject var itemData : ItemObject
    @State var putItem : Tool
    @State var Width : CGFloat
    @State var Height : CGFloat
    @State var X : CGFloat
    @State var Y : CGFloat

    var body: some View {
        if !itemData.itemArray.contains(putItem) && !putItem.isTaken {
            {
                Image(putItem.image).resizable()
            }()
            .frame(minWidth: 0 ,maxWidth: Width, minHeight: 0 ,maxHeight: Height)
            .offset(x: X, y: Y) 
            .onTapGesture {
                putItem.isTaken = true
                addItem(item: putItem)
                print(itemData.itemArray)
            }
        } else {

        }
    }
    // to add an item
    func addItem(item: Tool) {
        itemData.itemArray.append(item)
    }

}
이제 '도구' 옵션으로 주의를 돌려봅시다.도구 탭에서 스케치를 다시 확인합니다.
가져온 항목의 이미지가 격자선 형식으로 표시됩니다.
스케치와 같은 3*3 프로젝트 격자를 만들려면 lazyVGrid를 사용하십시오. 최신 버전에 추가되었습니다.
ToolsTab.swift

import SwiftUI

struct ToolsTab: View {

    @EnvironmentObject var itemData : ItemObject


    var cols = Array(repeating: GridItem(.flexible(), spacing:0), count:3)
    public var body: some View {
        VStack {
            LazyVGrid(columns: cols) {
                ForEach(0 ..< itemData.itemArray.count, id: \.self) { index in
                    {
                        Image(itemData.itemArray[index].image).resizable()
                    }()
                    .frame(minWidth: 100 ,maxWidth: 100, minHeight: 100 ,maxHeight: 100, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
                    .background(Color.white)
                    .overlay(
                        Rectangle()
                            .stroke(itemData.itemArray[index].isSelected ?  Color.red : Color.blue, lineWidth: 5)
                    ).onTapGesture {
                        itemData.itemArray[index].isSelected.toggle()
                        itemData.itemArray[index].isTaken = true
                    }
                }
            }
            Spacer()
            ToolTextPlate()
        }
    }

}

항목을 선택하면 해당 설명이 화면 하단의 대시 팔레트에 나타납니다.이 설명들은 게임의 난제를 해결하는 데 도움을 주는 중요한 힌트를 포함하고 있다.선택한 항목은 주 항목이 정지된 그룹과 같기 때문에 로고 등이 동기화됩니다.
여기서 나를 곤란하게 하는 것은 여러 항목을 선택할 때 설명이 서로 겹쳐 나타난다는 것이다.이 원인 때문에, 나는 모든 묘사를 읽을 수 없다.

이 문제를 해결하기 위해서 우리는 교묘한 과정을 사용해야 한다. 예를 들어 목록 보기에서 단일 선택을 해야 하지만 게임 설정에 따라 여러 항목을 동시에 사용할 수 있고 게임 기능에 부정적인 영향을 미치지 않기 때문에 우리는 원래의 모습을 유지할 것이다.아무도 이런 일에 관심이 없다.

인스턴스 정보


다음에 화면에 존재하는 항목을 계속 만들 것입니다.창 대상을 만들 때와 같은 기술을 사용할 것입니다.유일한 차이점은 항목의 절대 위치를 결정하기 위해 변수를 @State로 설정하는 것입니다.이해하기 쉬울 거야.변수를 사용하는 데는 세 가지 방법이 있다.
창 옆에 있는 코드는 다음과 같다.그것은 조직이 양호하여 조정하기 쉽다.
import SwiftUI

struct N_Window: View {

    @ObservedObject var windowObject = WindowObject.shared
    @ObservedObject var itemData = ItemObject.shared
    @ObservedObject var scriptData = ScriptObject.shared
    @ObservedObject var cycle = CycleChain.shared



    var body: some View {
        ZStack{
            BackGroundPicture(imageFilename: windowObject.window.image)
            WindowTool(putItem: $itemData.item1, Width: 100, Height: 100, X: 0, Y: 0)
            ZoomInButton(nextWindow: AnyView(N_Zoom_Window()), thisWindow: $windowObject.window, Width: 100, Height: 100, X: 0, Y: 100)
        }

    }

}


이제 완성됐습니다.너는 이 물건들이 매우 예쁘게 진열되어 있는 것을 볼 수 있다.이제 클릭을 통해 그것을 테스트합시다.

무슨 일이 생겼어요?매번 내가 스크린으로 돌아갈 때마다, 나는 내가 찍은 물건이 한 번 또 한 번 복제될 것이라고 생각했다.이 작은 고장이 문제다.만약 이것이 현금으로 바꿀 수 있는 블록체인 게임 앱이라면 그것은 회사에 심각한 파괴를 초래할 것이다.왜 이러지?나는 가설이 하나 있다.
화면을 다시 그릴 때마다 새 인스턴스가 생성되고 덮어쓰여집니다.swiftUI 기능은 관찰된 변수가 변경되었을 때 이 변수를 포함하는 보기를 다시 그리지만, 실례가 덮어쓰이기 때문에 변경된 변수, Bool 등은 유지보수되지 않습니다.이 관점도 마찬가지다.같은 일도 창구 대상에서 일어났지만 뚜렷하지 않았다.같은 일도 창의 대상에서 일어난다. 뚜렷하지 않지만, 창은 여러 번 다시 만들 수 있고, 눈은 여전히 완전히 보이지 않는다.일반적인 대상을 대상으로 프로그래밍한 경험을 가진 사람에게 이런 실례화 문제는 기본적인 문제이다.
이 문제를 해결하기 위해서 우리는 디자인 모델인 Singleton을 사용할 것이다.이것은 실례 생성 횟수를 제한하는 방법이다.지금까지 모델을 만든 모든 대상을 다시 작성합니다.
코드는 아래와 같다.
ToolModel.swift

import Foundation


struct Tool : Equatable, Identifiable {
    let id : Int
    var text: String
    var image: String
    var isTaken: Bool
    var isSelected: Bool
}


class ItemObject: ObservableObject {
    //add this
    static let shared = ItemObject()
    private init(){}

    @Published var item1 = Tool(id: 1, text: "This is item 1", image: "item1.png", isTaken: false, isSelected: false)
    @Published var item2 = Tool(id: 2, text: "This is item 2", image: "item2.png", isTaken: false, isSelected: false)
    @Published var item3 = Tool(id: 3, text: "This is item 3", image: "item3.png", isTaken: false, isSelected: false)
    @Published var item4 = Tool(id: 4, text: "This is item 4", image: "item4.png", isTaken: false, isSelected: false)
    @Published var item5 = Tool(id: 5, text: "This is item 5", image: "item5.png", isTaken: false, isSelected: false)
    @Published var item6 = Tool(id: 6, text: "This is item 6", image: "item6.png", isTaken: false, isSelected: false)
    @Published var item7 = Tool(id: 7, text: "This is item 7", image: "item7.png", isTaken: false, isSelected: false)
    @Published var item8 = Tool(id: 8, text: "This is item 8", image: "item8.png", isTaken: false, isSelected: false)
    @Published var item9 = Tool(id: 9, text: "This is item 9", image: "item9.png", isTaken: false, isSelected: false)

    // empty arrays
    @Published var itemArray: [Tool] = []



}

WindowModel.swift

import Foundation



struct WindowModel {
    var id : Int
    var image: String
    var isZoom : Bool
}

class WindowObject : ObservableObject {
    //add this
    static let shared = WindowObject()
    private init(){}

    @Published var window = WindowModel(id: 1, image: "window1", isZoom: false)
    @Published var window1 = WindowModel(id: 2, image: "window2", isZoom: false)
    @Published var window2 = WindowModel(id: 3, image: "window1doordark", isZoom: false)
    @Published var window3 = WindowModel(id: 4, image: "window2door", isZoom: false)
    @Published var window4 = WindowModel(id: 5, image: "window1dark", isZoom: false)
    @Published var window5 = WindowModel(id: 6, image: "window2dark", isZoom: false)
}

그리고
import SwiftUI

struct WindowTool: View {

    @ObservedObject var itemData = ItemObject.shared
    @ObservedObject var cycle = CycleChain.shared
    // changed State to Binding
    @Binding var putItem : Tool
    @State var Width : CGFloat
    @State var Height : CGFloat
    @State var X : CGFloat
    @State var Y : CGFloat

    var body: some View {
        if !itemData.itemArray.contains(putItem) && !putItem.isTaken {
            {
                Image(putItem.image).resizable()
            }()
            .frame(minWidth: 0 ,maxWidth: Width, minHeight: 0 ,maxHeight: Height)
            .offset(x: X, y: Y) 
            .onTapGesture {
                putItem.isTaken = true
                addItem(item: putItem)
                print(itemData.itemArray)
            }
        } else {

        }
    }
    // to add an item
    func addItem(item: Tool) {
        itemData.itemArray.append(item)
    }

}

그리고 다시 운전해 봅시다.

그러나 상황은 개선되지 않았다.이것은 사실상 @State를 사용할 때 구조가 원형대로 복사되기 때문에 변수의 변경 사항을 저장할 수 없습니다.그래서 @Binding을 다시 쓰고 $mark를 추가합니다.이 경우 $태그를 사용합니다.그리고 나서 상황이 해결되었다.@Binding과 @Published를 사용하면 데이터 변경 사항이 모든 보기에 반영되지만, 더 많은 정보를 알아야 합니다.
우리는 다음과 같은 방식으로 모든 코드를 수정하면 이 문제를 해결할 수 있다는 것을 확인했다.데이터 흐름은 swiftUI의 핵심 사상이며 매우 깊이 있다.반대로, 이 생각을 이해하게 되면, swiftUI를 걱정할 필요가 없다.

좋은 웹페이지 즐겨찾기