Full Code of windstormeye/SwiftGame for AI

master d2f4eefc9e28 cached
114 files
179.6 KB
58.1k tokens
1 requests
Download .txt
Showing preview only (214K chars total). Download the full file or copy to clipboard to get everything.
Repository: windstormeye/SwiftGame
Branch: master
Commit: d2f4eefc9e28
Files: 114
Total size: 179.6 KB

Directory structure:
gitextract_jbiqqmeb/

├── LICENSE
├── README.md
├── bounceGame/
│   ├── bounceGame/
│   │   ├── Actions.sks
│   │   ├── AppDelegate.swift
│   │   ├── Assets.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   └── Contents.json
│   │   ├── Ball/
│   │   │   ├── Ball.swift
│   │   │   ├── Box.swift
│   │   │   └── Label.swift
│   │   ├── Base.lproj/
│   │   │   ├── LaunchScreen.storyboard
│   │   │   └── Main.storyboard
│   │   ├── Define.swift
│   │   ├── Extension.swift
│   │   ├── GameScene.sks
│   │   ├── GameScene.swift
│   │   ├── GameViewController.swift
│   │   └── Info.plist
│   └── bounceGame.xcodeproj/
│       ├── project.pbxproj
│       ├── project.xcworkspace/
│       │   ├── contents.xcworkspacedata
│       │   ├── xcshareddata/
│       │   │   └── IDEWorkspaceChecks.plist
│       │   └── xcuserdata/
│       │       └── pjhubs.xcuserdatad/
│       │           └── UserInterfaceState.xcuserstate
│       └── xcuserdata/
│           └── pjhubs.xcuserdatad/
│               ├── xcdebugger/
│               │   └── Breakpoints_v2.xcbkptlist
│               └── xcschemes/
│                   └── xcschememanagement.plist
├── liGame/
│   ├── liGame/
│   │   ├── AppDelegate.swift
│   │   ├── Assets.xcassets/
│   │   │   ├── 01.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── AppIcon-1.appiconset/
│   │   │   │   └── Contents.json
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   ├── Contents.json
│   │   │   ├── Line0.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Line1.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Line2.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Line3.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_1.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_10.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_11.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_12.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_13.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_14.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_15.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_16.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_17.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_18.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_2.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_3.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_4.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_5.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_6.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_7.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_8.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_9.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── finalMan.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── finalManContent.imageset/
│   │   │       └── Contents.json
│   │   ├── Base.lproj/
│   │   │   ├── LaunchScreen.storyboard
│   │   │   └── Main.storyboard
│   │   ├── Extension/
│   │   │   ├── Animation.swift
│   │   │   ├── Define.swift
│   │   │   ├── UIColor+Extension.swift
│   │   │   ├── UIImage+Extension.swift
│   │   │   └── UIView+Extension.swift
│   │   ├── Info.plist
│   │   ├── View/
│   │   │   ├── Bottom/
│   │   │   │   ├── LiBottomCollectionView.swift
│   │   │   │   ├── LiBottomCollectionViewCell.swift
│   │   │   │   └── LiBottomView.swift
│   │   │   └── Puzzle.swift
│   │   └── ViewController.swift
│   └── liGame.xcodeproj/
│       ├── project.pbxproj
│       ├── project.xcworkspace/
│       │   ├── contents.xcworkspacedata
│       │   ├── xcshareddata/
│       │   │   └── IDEWorkspaceChecks.plist
│       │   └── xcuserdata/
│       │       ├── pjhubs.xcuserdatad/
│       │       │   └── UserInterfaceState.xcuserstate
│       │       └── wengpeijun.xcuserdatad/
│       │           └── UserInterfaceState.xcuserstate
│       └── xcuserdata/
│           ├── pjhubs.xcuserdatad/
│           │   ├── xcdebugger/
│           │   │   └── Breakpoints_v2.xcbkptlist
│           │   └── xcschemes/
│           │       └── xcschememanagement.plist
│           └── wengpeijun.xcuserdatad/
│               ├── xcdebugger/
│               │   └── Breakpoints_v2.xcbkptlist
│               └── xcschemes/
│                   └── xcschememanagement.plist
└── lightGame/
    ├── light-game/
    │   ├── AppDelegate.swift
    │   ├── Assets.xcassets/
    │   │   ├── AppIcon.appiconset/
    │   │   │   └── Contents.json
    │   │   └── Contents.json
    │   ├── Base.lproj/
    │   │   └── LaunchScreen.storyboard
    │   ├── ContentView.swift
    │   ├── Info.plist
    │   ├── Model/
    │   │   ├── GameController.swift
    │   │   ├── GameManager.swift
    │   │   └── Light.swift
    │   ├── Preview Content/
    │   │   └── Preview Assets.xcassets/
    │   │       └── Contents.json
    │   └── SceneDelegate.swift
    ├── light-game.xcodeproj/
    │   ├── project.pbxproj
    │   ├── project.xcworkspace/
    │   │   ├── contents.xcworkspacedata
    │   │   ├── xcshareddata/
    │   │   │   └── IDEWorkspaceChecks.plist
    │   │   └── xcuserdata/
    │   │       ├── pjhubs.xcuserdatad/
    │   │       │   └── UserInterfaceState.xcuserstate
    │   │       └── wengpeijun.xcuserdatad/
    │   │           └── UserInterfaceState.xcuserstate
    │   └── xcuserdata/
    │       ├── pjhubs.xcuserdatad/
    │       │   ├── xcdebugger/
    │       │   │   └── Breakpoints_v2.xcbkptlist
    │       │   └── xcschemes/
    │       │       └── xcschememanagement.plist
    │       └── wengpeijun.xcuserdatad/
    │           ├── xcdebugger/
    │           │   └── Breakpoints_v2.xcbkptlist
    │           └── xcschemes/
    │               └── xcschememanagement.plist
    ├── watchapp/
    │   ├── Assets.xcassets/
    │   │   ├── AppIcon.appiconset/
    │   │   │   └── Contents.json
    │   │   └── Contents.json
    │   ├── Base.lproj/
    │   │   └── Interface.storyboard
    │   └── Info.plist
    └── watchapp Extension/
        ├── Assets.xcassets/
        │   ├── Complication.complicationset/
        │   │   ├── Circular.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Contents.json
        │   │   ├── Extra Large.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Graphic Bezel.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Graphic Circular.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Graphic Corner.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Graphic Large Rectangular.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Modular.imageset/
        │   │   │   └── Contents.json
        │   │   └── Utilitarian.imageset/
        │   │       └── Contents.json
        │   └── Contents.json
        ├── ExtensionDelegate.swift
        ├── HostingController.swift
        ├── Info.plist
        ├── Preview Content/
        │   └── Preview Assets.xcassets/
        │       └── Contents.json
        ├── WatchContentView.swift
        └── WatchGameManager.swift

================================================
FILE CONTENTS
================================================

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2019 PJHubs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# 《Swift 游戏开发》

这里汇集了我的小专栏《Swift 游戏开发》的全部代码,小专栏地址:https://xiaozhuanlan.com/pjhubs-swift-game

![](https://images.xiaozhuanlan.com/photo/2019/4305214109ad56a7bbc8ed9e66c2bbf6.png)

[Swift 游戏开发序言](https://xiaozhuanlan.com/topic/9704163285)

![](https://images.xiaozhuanlan.com/photo/2019/22c830968d31df2249696119aa63d2db.png)

[Swift 游戏开发之能否关个灯(〇)](https://xiaozhuanlan.com/topic/9806127435)

[Swift 游戏开发之能否关个灯(一)](https://xiaozhuanlan.com/topic/2564017938)

[Swift 游戏开发之能否关个灯(二)](https://xiaozhuanlan.com/topic/8654723190)

![](https://images.xiaozhuanlan.com/photo/2019/a0dd4d112c81e08d47c1822a7a9888d0.png)

[Swift 游戏开发阶段总结(〇)](https://xiaozhuanlan.com/topic/7942150836)

![](https://images.xiaozhuanlan.com/photo/2019/d8805030d828cae0c691121d3d3c5ccb.png)

[Swift 游戏开发之黎锦拼图(〇)](https://xiaozhuanlan.com/topic/8079642315)

[Swift 游戏开发之黎锦拼图(一)](https://xiaozhuanlan.com/topic/0312569847)

[Swift 游戏开发之黎锦拼图(二)](https://xiaozhuanlan.com/topic/9738401526)

[Swift 游戏开发之黎锦拼图(三)](https://xiaozhuanlan.com/topic/3968275140)

[Swift 游戏开发之黎锦拼图(四)](https://xiaozhuanlan.com/topic/7436519820)

![](https://images.xiaozhuanlan.com/photo/2019/ac56d26bd4577bcdd242e2fe90141d6d.png)

[Swift 游戏开发阶段总结(一)](https://xiaozhuanlan.com/topic/8109647352)

![](https://images.xiaozhuanlan.com/photo/2019/e4fb08d3c028c97f5da6e62a7a08a6cd.png)

[Swift 游戏开发之方块弹珠(〇))](https://xiaozhuanlan.com/topic/1758926340)



================================================
FILE: bounceGame/bounceGame/AppDelegate.swift
================================================
//
//  AppDelegate.swift
//  bounceGame
//
//  Created by 翁培钧 on 2019/12/22.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }


}



================================================
FILE: bounceGame/bounceGame/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "3x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "83.5x83.5",
      "scale" : "2x"
    },
    {
      "idiom" : "ios-marketing",
      "size" : "1024x1024",
      "scale" : "1x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: bounceGame/bounceGame/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: bounceGame/bounceGame/Ball/Ball.swift
================================================
//
//  Ball.swift
//  bounceGame
//
//  Created by 翁培钧 on 2019/12/29.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import SpriteKit

class Ball: SKShapeNode {
    var isShot = false
    
    
    override init() {
        super.init()
        
        initObject()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func initObject() {
        self.fillColor = .red
        self.physicsBody = SKPhysicsBody(circleOfRadius: 10)
        self.physicsBody?.categoryBitMask = BitMask.Ball
        self.physicsBody?.contactTestBitMask = BitMask.Box | BitMask.Ground
        self.physicsBody?.collisionBitMask = BitMask.Box
        self.physicsBody?.usesPreciseCollisionDetection = true;
        self.physicsBody?.linearDamping = 0
        self.physicsBody?.restitution = 1.0
    }
}


================================================
FILE: bounceGame/bounceGame/Ball/Box.swift
================================================
//
//  Box.swift
//  bounceGame
//
//  Created by 翁培钧 on 2020/1/7.
//  Copyright © 2020 翁培钧. All rights reserved.
//

import SpriteKit

class Box: SKShapeNode {

}


================================================
FILE: bounceGame/bounceGame/Ball/Label.swift
================================================
//
//  Label.swift
//  bounceGame
//
//  Created by 翁培钧 on 2020/1/8.
//  Copyright © 2020 翁培钧. All rights reserved.
//

import SpriteKit

class Label: SKLabelNode {
    var typoTag = 0
}


================================================
FILE: bounceGame/bounceGame/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
</document>


================================================
FILE: bounceGame/bounceGame/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BV1-FR-VrT">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Game View Controller-->
        <scene sceneID="tXr-a1-R10">
            <objects>
                <viewController id="BV1-FR-VrT" customClass="GameViewController" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" multipleTouchEnabled="YES" contentMode="scaleToFill" id="3se-qz-xqx" customClass="SKView">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
                        <viewLayoutGuide key="safeArea" id="4qk-I5-YsI"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="SZV-WD-TEh" sceneMemberID="firstResponder"/>
            </objects>
        </scene>
    </scenes>
</document>


================================================
FILE: bounceGame/bounceGame/Define.swift
================================================
//
//  Define.swift
//  bounceGame
//
//  Created by 翁培钧 on 2019/12/30.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import Foundation


struct BitMask {
    static let Ball = UInt32(0x00001)
    static let Box = UInt32(0x00002)
    static let Wall = UInt32(0x00003)
    static let Ground = UInt32(0x00004)
}


================================================
FILE: bounceGame/bounceGame/Extension.swift
================================================
//
//  Extension.swift
//  bounceGame
//
//  Created by 翁培钧 on 2020/1/8.
//  Copyright © 2020 翁培钧. All rights reserved.
//

import SpriteKit




================================================
FILE: bounceGame/bounceGame/GameScene.swift
================================================
//
//  GameScene.swift
//  bounceGame
//
//  Created by 翁培钧 on 2019/12/22.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import SpriteKit

class GameScene: SKScene {
    
    private var balls = [Ball]()
    private var contactGroundBalls = [Ball]()
    
    
    private var isBegin = false
    
    
    private var ground = SKSpriteNode()
    private var firstDownBall: Ball?
    
    
    
    
    override init(size: CGSize) {
        super.init(size: size)
        
        physicsWorld.gravity = CGVector(dx: 0, dy: -1)
        physicsWorld.contactDelegate = self
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    var contentCreated = false
    
    override func didMove(to view: SKView) {
        if !contentCreated {
            createContent()
            contentCreated = true
        }
    }
    
    private func createContent() {
        ground = SKSpriteNode(color: .gray, size: CGSize(width: size.width, height: 120))
        ground.position = CGPoint(x: size.width / 2, y: ground.size.height / 2)
        addChild(ground)
        ground.physicsBody = SKPhysicsBody(rectangleOf: ground.size)
        ground.physicsBody?.isDynamic = false
        ground.physicsBody?.collisionBitMask = BitMask.Ball
        ground.physicsBody?.categoryBitMask = BitMask.Ground
        ground.physicsBody?.contactTestBitMask = BitMask.Ball
        
        let wall = SKNode()
        wall.position = CGPoint(x: 0, y: 0)
        wall.physicsBody?.friction = 0
        wall.physicsBody?.isDynamic = false
        wall.physicsBody?.restitution = 1.0
        wall.physicsBody?.collisionBitMask = BitMask.Wall
        wall.physicsBody?.categoryBitMask = BitMask.Wall
        wall.physicsBody?.contactTestBitMask = BitMask.Wall
        wall.physicsBody = SKPhysicsBody(edgeLoopFrom: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        addChild(wall)
        
        for _ in 0..<5 {
            let ball = Ball(circleOfRadius: 10)
            balls.append(ball)
            addChild(ball)
            ball.physicsBody?.isDynamic = false
            ball.position = CGPoint(x: size.width / 2, y: ground.frame.size.height + ball.frame.size.height / 2)
        }
        
        for row in 1...5 {
            let box = Box(rectOf: CGSize(width: 50, height: 50))
            box.position = CGPoint(x: 50 + (row * 50 + 20), y: (800 - row * 50 + 20))
            box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 50, height: 50))
            box.physicsBody?.categoryBitMask = BitMask.Box
            box.physicsBody?.contactTestBitMask = BitMask.Ball
            box.physicsBody?.collisionBitMask = BitMask.Box
            box.physicsBody?.linearDamping = 0
            box.physicsBody?.restitution = 1.0
            box.physicsBody?.isDynamic = false
            box.fillColor = .red
            
            let label = Label(text: "\(row)")
            label.fontSize = 22
            label.typoTag = 666
            label.fontName = "Arial-BoldMT"
            label.color = .white
            label.position = CGPoint(x: 0, y: -label.frame.size.height / 2)
            box.addChild(label)
            
            addChild(box)
        }
    }
}

extension GameScene {
    private func shot() {
        for (index, ball) in balls.enumerated() {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 * Double(index)) {
                ball.physicsBody?.isDynamic = true
                if (!self.children.contains(ball)) {
                    self.addChild(ball)
                }
                ball.physicsBody?.applyImpulse(CGVector(dx: 10, dy: 10))
                ball.physicsBody?.applyTorque(1.8)
//                ball.physicsBody?.applyForce(CGVector(dx: 400 + CGFloat(index) * 0.1, dy: 800))
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
                    ball.isShot = true
                    
                    if (index == self.balls.count - 1) {
                        self.firstDownBall?.removeFromParent()
                        self.firstDownBall = nil
                    }
                }
            }
        }
    }
}

extension GameScene {
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        shot()
    }
}

extension GameScene: SKPhysicsContactDelegate {
    func didBegin(_ contact: SKPhysicsContact) {
        print("\(contact.bodyA.contactTestBitMask) == \(contact.bodyB.contactTestBitMask)")
        
        
        
        switch contact.bodyA.categoryBitMask {
        case BitMask.Box:
            checkNodeIsBox(contact.bodyA.node)
            checkNodeIsWall(contact.bodyB.node)
        case BitMask.Wall:
            checkNodeIsWall(contact.bodyB.node)
        case BitMask.Ground:
            checkNodeIsGround(contact.bodyB.node)
        default:
            break
        }
        
        switch contact.bodyB.categoryBitMask {
        case BitMask.Box:
            checkNodeIsBox(contact.bodyB.node)
            checkNodeIsWall(contact.bodyA.node)
        case BitMask.Wall:
            checkNodeIsWall(contact.bodyA.node)
        case BitMask.Ground:
            checkNodeIsGround(contact.bodyA.node)
        default:
            break
        }
    }
}

extension GameScene {
    private func checkNodeIsBox(_ node: SKNode?) {
        guard let box = node else { return }
        
        if box.physicsBody?.categoryBitMask == BitMask.Box {
            let label = box.children.first! as! Label
            var tag = Int(label.text!)!
            if (tag > 1) {
                tag -= 1
                label.text = "\(tag)"
            } else {
                box.removeFromParent()
            }
        }
    }
    
    private func checkNodeIsWall(_ node: SKNode?) {
        guard let ball = node as? Ball else { return }
           
        ball.isShot = true
    }
    
    private func checkNodeIsGround(_ node: SKNode?) {
        guard let ball = node as? Ball else { return }
        
        // NOTE: 小球 & 发射出去
        if (ball.physicsBody?.categoryBitMask == BitMask.Ball && ball.isShot) {
            ball.removeFromParent();
            
            // NOTE: 定位小球不存在 || 当前 Scene 中不包含定位小球
            if (firstDownBall == nil || !children.contains(firstDownBall!)) {
                firstDownBall = Ball(circleOfRadius: 10)
                firstDownBall!.position = CGPoint(x: ball.position.x, y: ground.frame.size.height + ball.frame.size.height / 2 - 2)
                addChild(firstDownBall!)
                // NOTE: 静止
                firstDownBall!.physicsBody?.isDynamic = false
            }
        
            // NOTE: 统一重设后续触底小球位置。二次发射时,直接读取各个小球的初始位置进行发射
            ball.position = CGPoint(x: firstDownBall!.position.x, y: ground.frame.size.height + ball.frame.size.height / 2)
        }
    }
}



================================================
FILE: bounceGame/bounceGame/GameViewController.swift
================================================
//
//  GameViewController.swift
//  bounceGame
//
//  Created by 翁培钧 on 2019/12/22.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit
import SpriteKit

class GameViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let view = self.view as! SKView? {
            
            let scene = GameScene(size: view.frame.size)
            scene.scaleMode = .aspectFill
            view.presentScene(scene)
            view.ignoresSiblingOrder = true
            view.showsFPS = true
            view.showsNodeCount = true
            view.showsPhysics = true
        }
    }

    override var prefersStatusBarHidden: Bool {
        return true
    }
}


================================================
FILE: bounceGame/bounceGame/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UIStatusBarHidden</key>
	<true/>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: bounceGame/bounceGame.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 50;
	objects = {

/* Begin PBXBuildFile section */
		0C8BB82F23C4C84B00F88BD6 /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BB82E23C4C84B00F88BD6 /* Box.swift */; };
		0C964EBD23B8E5D0001EA659 /* Ball.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C964EBC23B8E5D0001EA659 /* Ball.swift */; };
		0C964EBF23BA3FDF001EA659 /* Define.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C964EBE23BA3FDF001EA659 /* Define.swift */; };
		0CA02F8523AFAB7D004A580E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA02F8423AFAB7D004A580E /* AppDelegate.swift */; };
		0CA02F8723AFAB7D004A580E /* GameScene.sks in Resources */ = {isa = PBXBuildFile; fileRef = 0CA02F8623AFAB7D004A580E /* GameScene.sks */; };
		0CA02F8923AFAB7D004A580E /* Actions.sks in Resources */ = {isa = PBXBuildFile; fileRef = 0CA02F8823AFAB7D004A580E /* Actions.sks */; };
		0CA02F8B23AFAB7D004A580E /* GameScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA02F8A23AFAB7D004A580E /* GameScene.swift */; };
		0CA02F8D23AFAB7D004A580E /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA02F8C23AFAB7D004A580E /* GameViewController.swift */; };
		0CA02F9023AFAB7D004A580E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0CA02F8E23AFAB7D004A580E /* Main.storyboard */; };
		0CA02F9223AFAB7E004A580E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0CA02F9123AFAB7E004A580E /* Assets.xcassets */; };
		0CA02F9523AFAB7E004A580E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0CA02F9323AFAB7E004A580E /* LaunchScreen.storyboard */; };
		0CFFFBBE23C629AD00BB3F13 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFFFBBD23C629AD00BB3F13 /* Label.swift */; };
		0CFFFBC223C62AD300BB3F13 /* Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFFFBC123C62AD300BB3F13 /* Extension.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
		0C8BB82E23C4C84B00F88BD6 /* Box.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Box.swift; sourceTree = "<group>"; };
		0C964EBC23B8E5D0001EA659 /* Ball.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ball.swift; sourceTree = "<group>"; };
		0C964EBE23BA3FDF001EA659 /* Define.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Define.swift; sourceTree = "<group>"; };
		0CA02F8123AFAB7D004A580E /* bounceGame.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = bounceGame.app; sourceTree = BUILT_PRODUCTS_DIR; };
		0CA02F8423AFAB7D004A580E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
		0CA02F8623AFAB7D004A580E /* GameScene.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = GameScene.sks; sourceTree = "<group>"; };
		0CA02F8823AFAB7D004A580E /* Actions.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Actions.sks; sourceTree = "<group>"; };
		0CA02F8A23AFAB7D004A580E /* GameScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScene.swift; sourceTree = "<group>"; };
		0CA02F8C23AFAB7D004A580E /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = "<group>"; };
		0CA02F8F23AFAB7D004A580E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
		0CA02F9123AFAB7E004A580E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		0CA02F9423AFAB7E004A580E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
		0CA02F9623AFAB7E004A580E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		0CFFFBBD23C629AD00BB3F13 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
		0CFFFBC123C62AD300BB3F13 /* Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extension.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		0CA02F7E23AFAB7D004A580E /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		0C964EBB23B8E5A6001EA659 /* Ball */ = {
			isa = PBXGroup;
			children = (
				0C964EBC23B8E5D0001EA659 /* Ball.swift */,
				0C8BB82E23C4C84B00F88BD6 /* Box.swift */,
				0CFFFBBD23C629AD00BB3F13 /* Label.swift */,
			);
			path = Ball;
			sourceTree = "<group>";
		};
		0CA02F7823AFAB7D004A580E = {
			isa = PBXGroup;
			children = (
				0CA02F8323AFAB7D004A580E /* bounceGame */,
				0CA02F8223AFAB7D004A580E /* Products */,
			);
			sourceTree = "<group>";
		};
		0CA02F8223AFAB7D004A580E /* Products */ = {
			isa = PBXGroup;
			children = (
				0CA02F8123AFAB7D004A580E /* bounceGame.app */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		0CA02F8323AFAB7D004A580E /* bounceGame */ = {
			isa = PBXGroup;
			children = (
				0CA02F8423AFAB7D004A580E /* AppDelegate.swift */,
				0CA02F8623AFAB7D004A580E /* GameScene.sks */,
				0CA02F8823AFAB7D004A580E /* Actions.sks */,
				0CA02F8A23AFAB7D004A580E /* GameScene.swift */,
				0CA02F8C23AFAB7D004A580E /* GameViewController.swift */,
				0C964EBE23BA3FDF001EA659 /* Define.swift */,
				0CFFFBC123C62AD300BB3F13 /* Extension.swift */,
				0C964EBB23B8E5A6001EA659 /* Ball */,
				0CA02F8E23AFAB7D004A580E /* Main.storyboard */,
				0CA02F9123AFAB7E004A580E /* Assets.xcassets */,
				0CA02F9323AFAB7E004A580E /* LaunchScreen.storyboard */,
				0CA02F9623AFAB7E004A580E /* Info.plist */,
			);
			path = bounceGame;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		0CA02F8023AFAB7D004A580E /* bounceGame */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 0CA02F9923AFAB7E004A580E /* Build configuration list for PBXNativeTarget "bounceGame" */;
			buildPhases = (
				0CA02F7D23AFAB7D004A580E /* Sources */,
				0CA02F7E23AFAB7D004A580E /* Frameworks */,
				0CA02F7F23AFAB7D004A580E /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = bounceGame;
			productName = bounceGame;
			productReference = 0CA02F8123AFAB7D004A580E /* bounceGame.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		0CA02F7923AFAB7D004A580E /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastSwiftUpdateCheck = 1120;
				LastUpgradeCheck = 1120;
				ORGANIZATIONNAME = "翁培钧";
				TargetAttributes = {
					0CA02F8023AFAB7D004A580E = {
						CreatedOnToolsVersion = 11.2.1;
					};
				};
			};
			buildConfigurationList = 0CA02F7C23AFAB7D004A580E /* Build configuration list for PBXProject "bounceGame" */;
			compatibilityVersion = "Xcode 9.3";
			developmentRegion = en;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = 0CA02F7823AFAB7D004A580E;
			productRefGroup = 0CA02F8223AFAB7D004A580E /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				0CA02F8023AFAB7D004A580E /* bounceGame */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		0CA02F7F23AFAB7D004A580E /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				0CA02F9023AFAB7D004A580E /* Main.storyboard in Resources */,
				0CA02F8723AFAB7D004A580E /* GameScene.sks in Resources */,
				0CA02F9223AFAB7E004A580E /* Assets.xcassets in Resources */,
				0CA02F9523AFAB7E004A580E /* LaunchScreen.storyboard in Resources */,
				0CA02F8923AFAB7D004A580E /* Actions.sks in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		0CA02F7D23AFAB7D004A580E /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				0C964EBD23B8E5D0001EA659 /* Ball.swift in Sources */,
				0CA02F8B23AFAB7D004A580E /* GameScene.swift in Sources */,
				0CA02F8D23AFAB7D004A580E /* GameViewController.swift in Sources */,
				0C8BB82F23C4C84B00F88BD6 /* Box.swift in Sources */,
				0C964EBF23BA3FDF001EA659 /* Define.swift in Sources */,
				0CFFFBBE23C629AD00BB3F13 /* Label.swift in Sources */,
				0CA02F8523AFAB7D004A580E /* AppDelegate.swift in Sources */,
				0CFFFBC223C62AD300BB3F13 /* Extension.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXVariantGroup section */
		0CA02F8E23AFAB7D004A580E /* Main.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				0CA02F8F23AFAB7D004A580E /* Base */,
			);
			name = Main.storyboard;
			sourceTree = "<group>";
		};
		0CA02F9323AFAB7E004A580E /* LaunchScreen.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				0CA02F9423AFAB7E004A580E /* Base */,
			);
			name = LaunchScreen.storyboard;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		0CA02F9723AFAB7E004A580E /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_ENABLE_OBJC_WEAK = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu11;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 13.2;
				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
				MTL_FAST_MATH = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
			};
			name = Debug;
		};
		0CA02F9823AFAB7E004A580E /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_ENABLE_OBJC_WEAK = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu11;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 13.2;
				MTL_ENABLE_DEBUG_INFO = NO;
				MTL_FAST_MATH = YES;
				SDKROOT = iphoneos;
				SWIFT_COMPILATION_MODE = wholemodule;
				SWIFT_OPTIMIZATION_LEVEL = "-O";
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		0CA02F9A23AFAB7E004A580E /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = U6J5965DZK;
				INFOPLIST_FILE = bounceGame/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.pjhubs.bounceGame;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5.0;
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		0CA02F9B23AFAB7E004A580E /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = U6J5965DZK;
				INFOPLIST_FILE = bounceGame/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.pjhubs.bounceGame;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5.0;
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		0CA02F7C23AFAB7D004A580E /* Build configuration list for PBXProject "bounceGame" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				0CA02F9723AFAB7E004A580E /* Debug */,
				0CA02F9823AFAB7E004A580E /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		0CA02F9923AFAB7E004A580E /* Build configuration list for PBXNativeTarget "bounceGame" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				0CA02F9A23AFAB7E004A580E /* Debug */,
				0CA02F9B23AFAB7E004A580E /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 0CA02F7923AFAB7D004A580E /* Project object */;
}


================================================
FILE: bounceGame/bounceGame.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:bounceGame.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: bounceGame/bounceGame.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IDEDidComputeMac32BitWarning</key>
	<true/>
</dict>
</plist>


================================================
FILE: bounceGame/bounceGame.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
   uuid = "F52A3FF6-A55D-463E-895F-7E3D1A48B3E6"
   type = "1"
   version = "2.0">
   <Breakpoints>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "CBBEE58E-AF60-4B1B-B0DC-67F6E289D242"
            shouldBeEnabled = "No"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "bounceGame/GameScene.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "179"
            endingLineNumber = "179"
            landmarkName = "checkNodeIsWall(_:)"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
   </Breakpoints>
</Bucket>


================================================
FILE: bounceGame/bounceGame.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>SchemeUserState</key>
	<dict>
		<key>bounceGame.xcscheme_^#shared#^_</key>
		<dict>
			<key>orderHint</key>
			<integer>0</integer>
		</dict>
	</dict>
</dict>
</plist>


================================================
FILE: liGame/liGame/AppDelegate.swift
================================================
//
//  AppDelegate.swift
//  liGame
//
//  Created by 翁培钧 on 2019/9/4.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }


}



================================================
FILE: liGame/liGame/Assets.xcassets/01.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "01.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/AppIcon-1.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "3x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "83.5x83.5",
      "scale" : "2x"
    },
    {
      "idiom" : "ios-marketing",
      "size" : "1024x1024",
      "scale" : "1x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "3x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "83.5x83.5",
      "scale" : "2x"
    },
    {
      "idiom" : "ios-marketing",
      "size" : "1024x1024",
      "scale" : "1x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/Line0.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "Line0@2x.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/Line1.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "Line1@2x.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/Line2.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "Line2@2x.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/Line3.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "Line3@2x.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_1.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_1.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_10.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_10.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_11.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_11.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_12.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_12.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_13.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_13.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_14.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_14.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_15.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_15.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_16.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_16.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_17.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_1.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_18.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_3.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_2.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_2.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_3.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_3.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_4.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_4.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_5.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_5.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_6.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_6.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_7.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_7.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_8.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_8.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/created_9.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "created_9.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/finalMan.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "finalMan.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Assets.xcassets/finalManContent.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "finalMamContent.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: liGame/liGame/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
</document>


================================================
FILE: liGame/liGame/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
        </scene>
    </scenes>
</document>


================================================
FILE: liGame/liGame/Extension/Animation.swift
================================================
//
//  Animation.swift
//  WWDC19
//
//  Created by PJHubs on 2019/3/20.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import UIKit

protocol PJParticleAnimationable {}

extension PJParticleAnimationable where Self: UIViewController {
    func startParticleAnimation(_ point : CGPoint) {
        let emitter = CAEmitterLayer()
        emitter.emitterPosition = point
        emitter.preservesDepth = true
        
        var cells = [CAEmitterCell]()
        for i in 0..<20 {
            let cell = CAEmitterCell()
            cell.velocity = 150
            cell.velocityRange = 100
            cell.scale = 0.7
            cell.scaleRange = 0.3
            cell.emissionLongitude = CGFloat(-Double.pi / 2)
            cell.emissionRange = CGFloat(Double.pi / 2)
            cell.lifetime = 3
            cell.lifetimeRange = 1.5
            cell.spin = CGFloat(Double.pi / 2)
            cell.spinRange = CGFloat(Double.pi / 2 / 2)
            cell.birthRate = 2
            cell.contents = UIImage(named: "Line\(i)")?.cgImage
            
            cells.append(cell)
        }
        emitter.emitterCells = cells
        view.layer.addSublayer(emitter)
    }

    func stopParticleAnimation() {
        view.layer.sublayers?.filter({ $0.isKind(of: CAEmitterLayer.self)}).first?.removeFromSuperlayer()
    }
}



================================================
FILE: liGame/liGame/Extension/Define.swift
================================================
//
//  Define.swift
//  liGame
//
//  Created by 翁培钧 on 2019/9/4.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

/// 屏幕宽
let screenWidth = UIScreen.main.bounds.size.width
/// 屏幕高
let screenHeight = UIScreen.main.bounds.size.height
/// 底部安全距离
let bottomSafeAreaHeight = UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0.0
///顶部的安全距离
let topSafeAreaHeight = UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0.0
/// 状态栏高度
let statusBarHeight = UIApplication.shared.statusBarFrame.height;
/// 导航栏高度
let navigationBarHeight = CGFloat(44 + topSafeAreaHeight)



================================================
FILE: liGame/liGame/Extension/UIColor+Extension.swift
================================================
//
//  UIColor+Extension.swift
//  liGame
//
//  Created by 翁培钧 on 2019/9/4.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

extension UIColor {
    class func rgb(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat) -> UIColor {
        return UIColor(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: 1)
    }
    
    class func rgba(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat, _ a: CGFloat) -> UIColor {
        return UIColor(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: a)
    }
    
    static var bgColor: UIColor {
        return rgb(29, 36, 73)
    }
}


================================================
FILE: liGame/liGame/Extension/UIImage+Extension.swift
================================================
//
//  UIImage+Extension.swift
//  liGame
//
//  Created by 翁培钧 on 2019/9/6.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

extension UIImage {
    /// 通过原图获取 rect 大小的图片
    func image(with rect: CGRect) -> UIImage {
        let scale: CGFloat = 2
        let x = rect.origin.x * scale
        let y = rect.origin.y * scale
        let w = rect.size.width * scale
        let h = rect.size.height * scale
        let finalRect = CGRect(x: x, y: y, width: w, height: h)
        
        let originImageRef = self.cgImage
        let finanImageRef = originImageRef!.cropping(to: finalRect)
        let finanImage = UIImage(cgImage: finanImageRef!, scale: scale, orientation: .up)
        
        return finanImage
    }
}


================================================
FILE: liGame/liGame/Extension/UIView+Extension.swift
================================================
//
//  UIView+Extension.swift
//  liGame
//
//  Created by 翁培钧 on 2019/9/4.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

extension UIView {
    
    static private let PJSCREEN_SCALE = UIScreen.main.scale
    
    private func getPixintegral(pointValue: CGFloat) -> CGFloat {
        return round(pointValue * UIView.PJSCREEN_SCALE) / UIView.PJSCREEN_SCALE
    }
    
    public var x: CGFloat {
        get {
            return self.frame.origin.x
        }
        set(x) {
            self.frame = CGRect.init(
                x: getPixintegral(pointValue: x),
                y: self.y,
                width: self.width,
                height: self.height
            )
        }
    }
    
    public var y: CGFloat {
        get {
            return self.frame.origin.y
        }
        set(y) {
            self.frame = CGRect.init(
                x: self.x,
                y: getPixintegral(pointValue: y),
                width: self.width,
                height: self.height
            )
        }
    }
    
    public var width: CGFloat {
        get {
            return self.frame.size.width
        }
        set(width) {
            self.frame = CGRect.init(
                x: self.x,
                y: self.y,
                width: getPixintegral(pointValue: width),
                height: self.height
            )
        }
    }
    
    public var height: CGFloat {
        get {
            return self.frame.size.height
        }
        set (height) {
            self.frame = CGRect.init(
                x: self.x,
                y: self.y,
                width: self.width,
                height: getPixintegral(pointValue: height)
            )
        }
    }
    
    public var bottom: CGFloat {
        get {
            return self.y + self.height
        }
        set(bottom) {
            self.y = bottom - self.height
        }
    }
    
    public var right: CGFloat {
        get {
            return self.x + self.width
        }
        set (right) {
            self.x = right - self.width
        }
    }
    
    public var left: CGFloat {
        get {
            return self.x
        }
        set(left) {
            self.x = left
        }
    }
    
    public var top: CGFloat {
        get {
            return self.y
        }
        set(top) {
            self.y = top
        }
    }
    
    public var centerX: CGFloat {
        get {
            return self.center.x
        }
        set(centerX) {
            self.center = CGPoint.init(
                x: getPixintegral(pointValue: centerX),
                y: self.center.y
            )
        }
    }
    
    public var centerY: CGFloat {
        get {
            return self.center.y
        }
        set (centerY) {
            self.center = CGPoint.init(x: self.center.x, y: getPixintegral(pointValue: centerY))
        }
    }
    
}

extension UIView {
    func insertRoundingCorners() {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 8.0, height: 8.0))
        let pathMaskLayer = CAShapeLayer()
        pathMaskLayer.frame = bounds
        pathMaskLayer.path = path.cgPath
        layer.mask = pathMaskLayer
    }

}


================================================
FILE: liGame/liGame/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: liGame/liGame/View/Bottom/LiBottomCollectionView.swift
================================================
//
//  LiBottomCollectionView.swift
//  liGame
//
//  Created by pjhubs on 2019/9/8.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

class LiBottomCollectionView: UICollectionView {

    var longTapBegan: ((Puzzle, CGPoint) -> ())?
    var longTapChange: ((CGPoint) -> ())?
    var longTapEnded: (() -> ())?
    

    let cellIdentifier = "PJLineCollectionViewCell"
    var viewModels = [Puzzle]()

    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
        super.init(frame: frame, collectionViewLayout: layout)
        initView()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    private func initView() {
        backgroundColor = .clear
        showsHorizontalScrollIndicator = false
        isPagingEnabled = true
//        isUserInteractionEnabled = true
        dataSource = self
        
        register(LiBottomCollectionViewCell.self, forCellWithReuseIdentifier: "LiBottomCollectionViewCell")
    }
}

extension LiBottomCollectionView: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return viewModels.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LiBottomCollectionViewCell", for: indexPath) as! LiBottomCollectionViewCell
        cell.cellIndex = indexPath.row
        cell.gameIndex = viewModels[indexPath.row].tag
        cell.viewModel = viewModels[indexPath.row]
        cell.longTapBegan = { [weak self] index in
            guard let self = self else { return }
            guard self.viewModels.count != 0 else { return }
            self.longTapBegan?(self.viewModels[index], cell.center)
        }
        cell.longTapChange = {
            self.longTapChange?($0)
        }
        cell.longTapEnded = {
            self.viewModels.remove(at: $0)
            self.reloadData()
            
            self.longTapEnded?()
        }
        
        return cell
    }
}


================================================
FILE: liGame/liGame/View/Bottom/LiBottomCollectionViewCell.swift
================================================
//
//  LiBottomCollectionViewCell.swift
//  liGame
//
//  Created by pjhubs on 2019/9/8.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

class LiBottomCollectionViewCell: UICollectionViewCell {
    var longTapBegan: ((Int) -> ())?
    var longTapChange: ((CGPoint) -> ())?
    var longTapEnded: ((Int) -> ())?
    
    var cellIndex: Int?
    var gameIndex: Int?
    
    private var img = UIImageView()
    private var tipLabel = UILabel()
    
    
    var viewModel: Puzzle? {
        didSet { setViewModel() }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        layer.borderWidth = 1
        layer.borderColor = UIColor.darkGray.cgColor
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowRadius = 10
        layer.shadowOffset = CGSize.zero
        layer.shadowOpacity = 1
        
        img.contentMode = .scaleAspectFit
        img.frame = CGRect(x: 0, y: 0, width: width, height: height)
        addSubview(img)

        
        tipLabel = UILabel(frame: CGRect(x: width - 10, y: top - 10, width: 17, height: 17))
        tipLabel.font = UIFont.systemFont(ofSize: 11)
        tipLabel.backgroundColor = UIColor.rgb(80, 80, 80)
        tipLabel.textColor = .white
        tipLabel.textAlignment = .center
        tipLabel.layer.cornerRadius = tipLabel.width / 2
        tipLabel.layer.masksToBounds = true
        addSubview(tipLabel)

        
        let longTapGesture = UILongPressGestureRecognizer(target: self, action: .longTap)
        addGestureRecognizer(longTapGesture)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setViewModel() {
        img.image = viewModel?.image
        tipLabel.text = "\(gameIndex!)"
    }
}

extension LiBottomCollectionViewCell {
    @objc
    fileprivate func longTap(_ longTapGesture: UILongPressGestureRecognizer) {
        guard let cellIndex = cellIndex else { return }
        
        switch longTapGesture.state {
        case .began:
            longTapBegan?(cellIndex)
        case .changed:
            var translation = longTapGesture.location(in: superview)
            
            let itemCount = 5
            if cellIndex > itemCount {
                translation.x = translation.x - CGFloat(cellIndex / itemCount * Int(screenWidth))
            }
            
            let point = CGPoint(x: translation.x, y: translation.y)
            longTapChange?(point)
        case .ended:
            longTapEnded?(cellIndex)
        default: break
        }
    }
}

private extension Selector {
    static let longTap = #selector(LiBottomCollectionViewCell.longTap(_:))
}


================================================
FILE: liGame/liGame/View/Bottom/LiBottomView.swift
================================================
//
//  LiBottomView.swift
//  liGame
//
//  Created by pjhubs on 2019/9/8.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

class LiBottomView: UIView {
    var viewModels = [Puzzle]() {
        didSet { collectionView!.viewModels = viewModels }
    }

    var moveBegin: ((Puzzle) -> Void)?
    var moveChanged: ((CGPoint) -> Void)?
    var moveEnd: ((Puzzle) -> Void)?
    
    var tempPuzzle: Puzzle?
    var collectionView: LiBottomCollectionView?
    var longPressView: UIView?
    
    private var rightPoint: CGFloat = 0
    private var leftaPoint: CGFloat = 0
    private var topPoint: CGFloat = 0
    private var bottomPoint: CGFloat = 0
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    convenience init(frame: CGRect, longPressView: UIView?) {
        self.init(frame: frame)
        self.longPressView = self
        initView()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    private func initView() {
        backgroundColor = .clear
        
        topPoint = topSafeAreaHeight
        bottomPoint = screenHeight - bottomSafeAreaHeight
        rightPoint = screenWidth / 2
        leftaPoint = 0
        
        let effect = UIBlurEffect(style: .extraLight)
        let effectView = UIVisualEffectView(effect: effect)
        effectView.frame = CGRect(x: 0, y: 0, width: width, height: height)
        addSubview(effectView)
        
        insertRoundingCorners()
        
        let collectionViewLayout = UICollectionViewFlowLayout()
        let itemW = 50
        let innerW = (screenWidth - 5 * 50) / 5
        collectionViewLayout.itemSize = CGSize(width: itemW , height: itemW)
        collectionViewLayout.minimumLineSpacing = innerW
        collectionViewLayout.minimumInteritemSpacing = 10
        collectionViewLayout.scrollDirection = .horizontal
        collectionViewLayout.sectionInset = UIEdgeInsets.init(top: 0, left: innerW / 2, bottom: 0, right: innerW / 2)
        
        
        collectionView = LiBottomCollectionView(frame: CGRect(x: 0, y: 0, width: width, height: height), collectionViewLayout: collectionViewLayout)
        addSubview(collectionView!)
        collectionView!.longTapBegan = {
            let center = $1
            let tempPuzzle = Puzzle(size: $0.frame.size, isCopy: false)
            // 补上游戏索引 tag
            tempPuzzle.tag = $0.tag
            tempPuzzle.image = $0.image
            tempPuzzle.center = center
            tempPuzzle.y += self.top
            self.tempPuzzle = tempPuzzle
            
            self.moveBegin?(tempPuzzle)
        }
        collectionView!.longTapChange = {
            guard let tempPuzzle = self.tempPuzzle else { return }
            tempPuzzle.center = CGPoint(x: $0.x, y: $0.y + self.top)

            if tempPuzzle.right > self.rightPoint {
                tempPuzzle.right = self.rightPoint
            }
            if tempPuzzle.left < self.leftaPoint {
                tempPuzzle.left = self.leftaPoint
            }
            if tempPuzzle.top < self.topPoint {
                tempPuzzle.top = self.topPoint
            }
            if tempPuzzle.bottom > self.bottomPoint {
                tempPuzzle.bottom = self.bottomPoint
            }
            
            self.moveChanged?(tempPuzzle.center)
        }
        collectionView!.longTapEnded = {
            guard let tempPuzzle = self.tempPuzzle else { return }
            self.moveEnd?(tempPuzzle)
        }
    }
}

extension LiBottomView {
    @objc
    fileprivate func pan(_ panGesture: UIPanGestureRecognizer) {
        let translation = panGesture.translation(in: superview)
        panGesture.view!.center = CGPoint(x: panGesture.view!.center.x + translation.x,
                                          y: panGesture.view!.center.y + translation.y)
        panGesture.setTranslation(.zero, in: superview)
    }
}

private extension Selector {
    static let pan = #selector(LiBottomView.pan(_:))
}


================================================
FILE: liGame/liGame/View/Puzzle.swift
================================================
//
//  Puzzle.swift
//  liGame
//
//  Created by 翁培钧 on 2019/9/6.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

class Puzzle: UIImageView {

    var panChange: ((CGPoint) -> ())?
    var panEnded: (() -> ())?
    var beginMovedPoint = CGPoint()
    // 当前在 X 轴上的位置
    var Xindex: Int?
    // 当前在 Y 轴上的位置
    var Yindex: Int?
    
    /// 是否为「拷贝」拼图元素
    private var isCopy = false
    private var rightPoint: CGFloat = 0
    private var leftaPoint: CGFloat = 0
    private var topPoint: CGFloat = 0
    private var bottomPoint: CGFloat = 0
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    convenience init(size: CGSize, isCopy: Bool) {
        self.init(frame: CGRect(x: -1000, y: -1000, width: size.width, height: size.height))
        self.isCopy = isCopy
        
        initView()
    }
    
    
    // MARK: Init
    
    private func initView() {
        // 全部靠左,copyPuzzle 镜像对称
        contentMode = .left
        
        if !isCopy {
            isUserInteractionEnabled = true
            
            let panGesture = UIPanGestureRecognizer(target: self, action: .pan)
            self.addGestureRecognizer(panGesture)
        } else {
            transform = CGAffineTransform(scaleX: -1, y: 1)
        }
    }
    
    /// 更新边界
    func updateEdge() {
        if superview != nil {
            if !isCopy {
                topPoint = topSafeAreaHeight
                bottomPoint = superview!.bottom - bottomSafeAreaHeight
                rightPoint = superview!.width / 2
                leftaPoint = 0
            }
        } else {
            if superview != nil {
                topPoint = superview!.top
                bottomPoint = superview!.bottom
                rightPoint = superview!.width
                leftaPoint = superview!.width / 2
            }
        }
    }
    
    /// 移动 `rightPuzzle`
    func copyPuzzleCenterChange(centerPoint: CGPoint) {
        if !isCopy { return }
        center = CGPoint(x: screenWidth - centerPoint.x, y: centerPoint.y)
    }
    
}


extension Puzzle {
    @objc
    fileprivate func pan(_ panGesture: UIPanGestureRecognizer) {
        let translation = panGesture.translation(in: superview)
        
        switch panGesture.state {
        case .began:
            beginMovedPoint = center
            layer.borderColor = UIColor.white.cgColor
            layer.borderWidth = 1
        case .changed:
            if right > rightPoint {
                right = rightPoint
            }
            if left < leftaPoint {
                left = leftaPoint
            }
            if top < topPoint {
                top = topPoint
            }
            if bottom > bottomPoint {
                bottom = bottomPoint
            }
            
        case .ended:
            layer.borderWidth = 0
            self.panEnded?()
        default: break
        }
        
        center = CGPoint(x: center.x + translation.x, y: center.y + translation.y)
        panGesture.setTranslation(.zero, in: superview)
        
        panChange?(center)
    }
}

private extension Selector {
    static let pan = #selector(Puzzle.pan(_:))
}


================================================
FILE: liGame/liGame/ViewController.swift
================================================
//
//  ViewController.swift
//  liGame
//
//  Created by 翁培钧 on 2019/9/4.
//  Copyright © 2019 翁培钧. All rights reserved.
//

import UIKit

class ViewController: UIViewController, PJParticleAnimationable {

    private var lineImageView = UIImageView()
    private var bottomView = LiBottomView()
    
    private var puzzles = [Puzzle]()
    private var defaultPuzzles = [Puzzle]()
    private var finalPuzzleTags = [[Int]]()
    private var leftPuzzles = [Puzzle]()
    private var rightPuzzles = [Puzzle]()
    
    private var tempCopyPuzzle: Puzzle?
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .bgColor
        self.winLabel.isHidden = true

        
        // 底图适配
        let contentImage = UIImage(named: "01")!
        let contentImageScale = view.width / contentImage.size.width
        let contentImageViewHeight = contentImage.size.height * contentImageScale
        
        let contentImageView = UIImageView(frame: CGRect(x: 0, y: topSafeAreaHeight, width: view.width, height: contentImageViewHeight))
        contentImageView.image = contentImage
        
        let imgView = UIImageView(frame: CGRect(x: view.width / 2, y: topSafeAreaHeight, width: 5, height: view.height - bottomSafeAreaHeight))
        view.addSubview(imgView)
        UIGraphicsBeginImageContext(imgView.frame.size) // 位图上下文绘制区域
        imgView.image?.draw(in: imgView.bounds)
        lineImageView = imgView
        
        let context:CGContext = UIGraphicsGetCurrentContext()!
        context.setLineCap(CGLineCap.square)
        context.setStrokeColor(UIColor.white.cgColor)
        context.setLineWidth(3)
        context.setLineDash(phase: 0, lengths: [10,20])
        context.move(to: CGPoint(x: 0, y: 0))
        context.addLine(to: CGPoint(x: 0, y: view.height))
        context.strokePath()
        
        imgView.image = UIGraphicsGetImageFromCurrentImageContext()
        
        // 一行六个
        let itemHCount = 3
        let itemW = Int(view.width / CGFloat(itemHCount * 2))
        let itemH = itemW
        let itemVCount = Int(contentImageView.height / CGFloat(itemW))
        
        finalPuzzleTags = Array(repeating: Array(repeating: -1, count: itemHCount), count: itemVCount)
        
        for itemY in 0..<itemVCount {
            for itemX in 0..<itemHCount {
                let x = itemW * itemX
                let y = itemW * itemY
                
                var finalItemW = itemW
                var finalItemH = itemH
            
                //
                if itemX == itemHCount - 1 {
                    finalItemW = itemW / 3 * 2 + 2
                }
                
                let img = contentImageView.image!.image(with: CGRect(x: x, y: y, width: finalItemW, height: finalItemH))
                let puzzle = Puzzle(size: CGSize(width: itemW, height: itemW), isCopy: false)
                puzzle.image = img
                puzzle.tag = (itemY * itemHCount) + itemX
                puzzles.append(puzzle)
                defaultPuzzles.append(puzzle)
            }
        }
        
        for i in 1..<puzzles.count {
            let index = Int(arc4random()) % i
            if index != i {
                puzzles.swapAt(i, index)
            }
        }
        
        
        let bottomView = LiBottomView(frame: CGRect(x: 0, y: view.height, width: view.width, height: 64 + bottomSafeAreaHeight), longPressView: view)
        view.addSubview(bottomView)
        bottomView.viewModels = puzzles
        self.bottomView = bottomView
        
        bottomView.moveBegin = { puzzle in
            self.view.addSubview(puzzle)
            self.leftPuzzles.append(puzzle)
            puzzle.updateEdge()
            
            puzzle.panChange = {
                for copyPuzzle in self.rightPuzzles {
                    if copyPuzzle.tag == puzzle.tag {
                        copyPuzzle.copyPuzzleCenterChange(centerPoint: $0)
                    }
                }
            }
            
            puzzle.panEnded = {
                for copyPuzzle in self.rightPuzzles {
                    if copyPuzzle.tag == puzzle.tag {
                        self.adsorb(puzzle)
                        copyPuzzle.copyPuzzleCenterChange(centerPoint: puzzle.center)
                        if self.isWin() { self.winAnimate() }
                    }
                }
            }
            
            self.tempCopyPuzzle = Puzzle(size: puzzle.frame.size, isCopy: true)
            self.tempCopyPuzzle?.image = puzzle.image
            self.tempCopyPuzzle?.tag = puzzle.tag
            self.view.addSubview(self.tempCopyPuzzle!)
        }
        
        bottomView.moveChanged = {
            guard let tempPuzzle = self.tempCopyPuzzle else { return }
            
            // 超出底部功能栏位置后才显示
            if $0.y < self.bottomView.top {
                tempPuzzle.copyPuzzleCenterChange(centerPoint: $0)
            }
            
        }
        
        bottomView.moveEnd = {
            guard let tempPuzzle = self.tempCopyPuzzle else { return }
            tempPuzzle.removeFromSuperview()
            
            let copyPuzzle = Puzzle(size: $0.frame.size, isCopy: true)
            copyPuzzle.image = tempPuzzle.image
            copyPuzzle.tag = tempPuzzle.tag
            self.view.addSubview(copyPuzzle)
            self.rightPuzzles.append(copyPuzzle)
            
            self.adsorb(self.leftPuzzles.last!)
            copyPuzzle.copyPuzzleCenterChange(centerPoint: self.leftPuzzles.last!.center)
        
            if self.isWin() { self.winAnimate() }
        }
        
        
        UIView.animate(withDuration: 0.25, delay: 0.5, options: .curveEaseIn, animations: {
            bottomView.bottom = self.view.height
        })
        
    }
    
    
    /// 启动磁吸
    private func adsorb(_ tempPuzzle: Puzzle) {
        var tempPuzzleCenterPoint = tempPuzzle.center
        
        var tempPuzzleXIndex = CGFloat(Int(tempPuzzleCenterPoint.x / tempPuzzle.width))
        if Int(tempPuzzleCenterPoint.x) % Int(tempPuzzle.width) > 0 {
            tempPuzzleXIndex += 1
        }
        
        var tempPuzzleYIndex = CGFloat(Int(tempPuzzleCenterPoint.y / tempPuzzle.height))
        if Int(tempPuzzleCenterPoint.y) % Int(tempPuzzle.height) > 0 {
            tempPuzzleYIndex += 1
        }
        
        
        let Xedge = tempPuzzleXIndex * tempPuzzle.width
        let Yedge = tempPuzzleYIndex * tempPuzzle.height
        
        if tempPuzzleCenterPoint.x < Xedge {
            tempPuzzleCenterPoint.x = Xedge - tempPuzzle.width / 2
        }
        
        if tempPuzzleCenterPoint.y < Yedge {
            // 当为最后一列时,往上移 20
            if (Int(tempPuzzleYIndex) == finalPuzzleTags.count) {
                tempPuzzleCenterPoint.y = Yedge  - tempPuzzle.height / 2 - 20
            } else {
                tempPuzzleCenterPoint.y = Yedge  - tempPuzzle.height / 2
            }
        }
        
        // 超出最下边
        if (Int(tempPuzzleYIndex) > self.finalPuzzleTags.count) {
            tempPuzzle.center = tempPuzzle.beginMovedPoint
        }
        
        // 已经有的不能占据
        if (self.finalPuzzleTags[Int(tempPuzzleYIndex - 1)][Int(tempPuzzleXIndex - 1)] == -1) {
            self.finalPuzzleTags[Int(tempPuzzleYIndex - 1)][Int(tempPuzzleXIndex - 1)] = tempPuzzle.tag
            
            
            if ((tempPuzzle.Xindex != nil) && (tempPuzzle.Yindex != nil)) {
                self.finalPuzzleTags[tempPuzzle.Xindex!][tempPuzzle.Yindex!] = -1
            }
            
            tempPuzzle.Xindex = Int(tempPuzzleYIndex - 1)
            tempPuzzle.Yindex = Int(tempPuzzleXIndex - 1)
            
            tempPuzzle.center = tempPuzzleCenterPoint
        } else {
            tempPuzzle.center = tempPuzzle.beginMovedPoint
        }
    }
    
    /// 判赢算法
    private func isWin() -> Bool {
        
        var winCount = 0
        for (Vindex, HTags) in self.finalPuzzleTags.enumerated() {
            for (Hindex, tag) in HTags.enumerated() {
                let currentIndex = Vindex * 3 + Hindex
                if defaultPuzzles.count - 1 >= currentIndex {
                    if defaultPuzzles[currentIndex].tag == tag {
                        winCount += 1
                        continue
                    }
                }
                
                return false
            }
        }
        
        if winCount == defaultPuzzles.count {
            return true
        }
        return false
    }

        
    private func winAnimate() {
        startParticleAnimation(CGPoint(x: screenWidth / 2, y: screenHeight - 10))
        
        UIView.animate(withDuration: 0.25, animations: {
            self.bottomView.top = screenHeight
        })
        
        for sv in self.view.subviews {
            sv.removeFromSuperview()
        }
        
        self.winLabel.isHidden = false
        let finalManContentView = UIImageView(frame: CGRect(x: 0, y: 0,
                                                            width: screenWidth,
                                                            height: screenHeight - 64))
        finalManContentView.image = UIImage(named: "finalManContent")
        self.view.addSubview(finalManContentView)
        
        let finalMan = UIImageView(frame: CGRect(x: 0, y: 0,
                                                 width: finalManContentView.width * 0.85,
                                                 height: finalManContentView.width * 0.8 * 0.85))
        finalMan.center = self.view.center
        finalMan.image = UIImage(named: "finalMan")
        self.view.addSubview(finalMan)
        
        
        UIView.animate(withDuration: 0.5, animations: {
            finalMan.transform = CGAffineTransform(rotationAngle: 0.25)
        }) { (finished) in
            UIView.animate(withDuration: 0.5, animations: {
                finalMan.transform = CGAffineTransform(rotationAngle: -0.25)
            }, completion: { (finished) in
                UIView.animate(withDuration: 0.5, animations: {
                    finalMan.transform = CGAffineTransform(rotationAngle: 0)
                })
            })
        }
    }
    
    
    // MARK: - Lazy
    lazy var winLabel: UILabel = {
        let label = UILabel(frame: CGRect(x: 0, y: screenHeight - 64,
                                          width: screenWidth, height: 64))
        label.centerX = view.centerX
        label.font = UIFont.systemFont(ofSize: 40,
                                       weight: UIFont.Weight.light)
        label.text = "Dàlì shén"
        label.textAlignment = .center
        label.textColor = .white
        view.addSubview(label)
        return label
    }()
}


================================================
FILE: liGame/liGame.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 50;
	objects = {

/* Begin PBXBuildFile section */
		0C7ACB9C2322A97000AA4FA4 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C7ACB9B2322A97000AA4FA4 /* UIImage+Extension.swift */; };
		0C99777123200DE600EA0130 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C99777023200DE600EA0130 /* AppDelegate.swift */; };
		0C99777323200DE600EA0130 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C99777223200DE600EA0130 /* ViewController.swift */; };
		0C99777623200DE600EA0130 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0C99777423200DE600EA0130 /* Main.storyboard */; };
		0C99777823200DE700EA0130 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0C99777723200DE700EA0130 /* Assets.xcassets */; };
		0C99777B23200DE700EA0130 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0C99777923200DE700EA0130 /* LaunchScreen.storyboard */; };
		0C9977832320135200EA0130 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C9977822320135200EA0130 /* UIView+Extension.swift */; };
		0C997785232013C300EA0130 /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C997784232013C300EA0130 /* UIColor+Extension.swift */; };
		0C997788232014A500EA0130 /* Define.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C997787232014A500EA0130 /* Define.swift */; };
		0CAE10A62321E76900CFECA5 /* Puzzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CAE10A52321E76900CFECA5 /* Puzzle.swift */; };
		0CE27C0A2371C4950032CF94 /* Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE27C092371C4950032CF94 /* Animation.swift */; };
		A64F18812325121900F531F4 /* LiBottomCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A64F18802325121900F531F4 /* LiBottomCollectionView.swift */; };
		A64F18832325126800F531F4 /* LiBottomCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A64F18822325126800F531F4 /* LiBottomCollectionViewCell.swift */; };
		A64F18852325133E00F531F4 /* LiBottomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A64F18842325133E00F531F4 /* LiBottomView.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
		0C7ACB9B2322A97000AA4FA4 /* UIImage+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = "<group>"; };
		0C99776D23200DE600EA0130 /* liGame.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = liGame.app; sourceTree = BUILT_PRODUCTS_DIR; };
		0C99777023200DE600EA0130 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
		0C99777223200DE600EA0130 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
		0C99777523200DE600EA0130 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
		0C99777723200DE700EA0130 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		0C99777A23200DE700EA0130 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
		0C99777C23200DE700EA0130 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		0C9977822320135200EA0130 /* UIView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Extension.swift"; sourceTree = "<group>"; };
		0C997784232013C300EA0130 /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; };
		0C997787232014A500EA0130 /* Define.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Define.swift; sourceTree = "<group>"; };
		0CAE10A52321E76900CFECA5 /* Puzzle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Puzzle.swift; sourceTree = "<group>"; };
		0CE27C092371C4950032CF94 /* Animation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animation.swift; sourceTree = "<group>"; };
		A64F18802325121900F531F4 /* LiBottomCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiBottomCollectionView.swift; sourceTree = "<group>"; };
		A64F18822325126800F531F4 /* LiBottomCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiBottomCollectionViewCell.swift; sourceTree = "<group>"; };
		A64F18842325133E00F531F4 /* LiBottomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiBottomView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		0C99776A23200DE600EA0130 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		0C99776423200DE600EA0130 = {
			isa = PBXGroup;
			children = (
				0C99776F23200DE600EA0130 /* liGame */,
				0C99776E23200DE600EA0130 /* Products */,
			);
			sourceTree = "<group>";
		};
		0C99776E23200DE600EA0130 /* Products */ = {
			isa = PBXGroup;
			children = (
				0C99776D23200DE600EA0130 /* liGame.app */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		0C99776F23200DE600EA0130 /* liGame */ = {
			isa = PBXGroup;
			children = (
				0C99777023200DE600EA0130 /* AppDelegate.swift */,
				0C99777223200DE600EA0130 /* ViewController.swift */,
				0C9977892321E70900EA0130 /* View */,
				0C9977862320149900EA0130 /* Extension */,
				0C99777423200DE600EA0130 /* Main.storyboard */,
				0C99777723200DE700EA0130 /* Assets.xcassets */,
				0C99777923200DE700EA0130 /* LaunchScreen.storyboard */,
				0C99777C23200DE700EA0130 /* Info.plist */,
			);
			path = liGame;
			sourceTree = "<group>";
		};
		0C9977862320149900EA0130 /* Extension */ = {
			isa = PBXGroup;
			children = (
				0CE27C092371C4950032CF94 /* Animation.swift */,
				0C9977822320135200EA0130 /* UIView+Extension.swift */,
				0C997784232013C300EA0130 /* UIColor+Extension.swift */,
				0C997787232014A500EA0130 /* Define.swift */,
				0C7ACB9B2322A97000AA4FA4 /* UIImage+Extension.swift */,
			);
			path = Extension;
			sourceTree = "<group>";
		};
		0C9977892321E70900EA0130 /* View */ = {
			isa = PBXGroup;
			children = (
				A64F187F232511F500F531F4 /* Bottom */,
				0CAE10A52321E76900CFECA5 /* Puzzle.swift */,
			);
			path = View;
			sourceTree = "<group>";
		};
		A64F187F232511F500F531F4 /* Bottom */ = {
			isa = PBXGroup;
			children = (
				A64F18802325121900F531F4 /* LiBottomCollectionView.swift */,
				A64F18822325126800F531F4 /* LiBottomCollectionViewCell.swift */,
				A64F18842325133E00F531F4 /* LiBottomView.swift */,
			);
			path = Bottom;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		0C99776C23200DE600EA0130 /* liGame */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 0C99777F23200DE700EA0130 /* Build configuration list for PBXNativeTarget "liGame" */;
			buildPhases = (
				0C99776923200DE600EA0130 /* Sources */,
				0C99776A23200DE600EA0130 /* Frameworks */,
				0C99776B23200DE600EA0130 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = liGame;
			productName = liGame;
			productReference = 0C99776D23200DE600EA0130 /* liGame.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		0C99776523200DE600EA0130 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastSwiftUpdateCheck = 1020;
				LastUpgradeCheck = 1020;
				ORGANIZATIONNAME = "翁培钧";
				TargetAttributes = {
					0C99776C23200DE600EA0130 = {
						CreatedOnToolsVersion = 10.2.1;
					};
				};
			};
			buildConfigurationList = 0C99776823200DE600EA0130 /* Build configuration list for PBXProject "liGame" */;
			compatibilityVersion = "Xcode 9.3";
			developmentRegion = en;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = 0C99776423200DE600EA0130;
			productRefGroup = 0C99776E23200DE600EA0130 /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				0C99776C23200DE600EA0130 /* liGame */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		0C99776B23200DE600EA0130 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				0C99777B23200DE700EA0130 /* LaunchScreen.storyboard in Resources */,
				0C99777823200DE700EA0130 /* Assets.xcassets in Resources */,
				0C99777623200DE600EA0130 /* Main.storyboard in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		0C99776923200DE600EA0130 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				0CE27C0A2371C4950032CF94 /* Animation.swift in Sources */,
				A64F18812325121900F531F4 /* LiBottomCollectionView.swift in Sources */,
				0C9977832320135200EA0130 /* UIView+Extension.swift in Sources */,
				0C7ACB9C2322A97000AA4FA4 /* UIImage+Extension.swift in Sources */,
				0C99777323200DE600EA0130 /* ViewController.swift in Sources */,
				A64F18832325126800F531F4 /* LiBottomCollectionViewCell.swift in Sources */,
				0C99777123200DE600EA0130 /* AppDelegate.swift in Sources */,
				0CAE10A62321E76900CFECA5 /* Puzzle.swift in Sources */,
				0C997788232014A500EA0130 /* Define.swift in Sources */,
				A64F18852325133E00F531F4 /* LiBottomView.swift in Sources */,
				0C997785232013C300EA0130 /* UIColor+Extension.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXVariantGroup section */
		0C99777423200DE600EA0130 /* Main.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				0C99777523200DE600EA0130 /* Base */,
			);
			name = Main.storyboard;
			sourceTree = "<group>";
		};
		0C99777923200DE700EA0130 /* LaunchScreen.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				0C99777A23200DE700EA0130 /* Base */,
			);
			name = LaunchScreen.storyboard;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		0C99777D23200DE700EA0130 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_ENABLE_OBJC_WEAK = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				CODE_SIGN_IDENTITY = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu11;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 12.2;
				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
				MTL_FAST_MATH = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
			};
			name = Debug;
		};
		0C99777E23200DE700EA0130 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_ENABLE_OBJC_WEAK = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				CODE_SIGN_IDENTITY = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu11;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 12.2;
				MTL_ENABLE_DEBUG_INFO = NO;
				MTL_FAST_MATH = YES;
				SDKROOT = iphoneos;
				SWIFT_COMPILATION_MODE = wholemodule;
				SWIFT_OPTIMIZATION_LEVEL = "-O";
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		0C99778023200DE700EA0130 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = U6J5965DZK;
				INFOPLIST_FILE = liGame/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.pjhubs.liGame;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5.0;
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		0C99778123200DE700EA0130 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = U6J5965DZK;
				INFOPLIST_FILE = liGame/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.pjhubs.liGame;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5.0;
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		0C99776823200DE600EA0130 /* Build configuration list for PBXProject "liGame" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				0C99777D23200DE700EA0130 /* Debug */,
				0C99777E23200DE700EA0130 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		0C99777F23200DE700EA0130 /* Build configuration list for PBXNativeTarget "liGame" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				0C99778023200DE700EA0130 /* Debug */,
				0C99778123200DE700EA0130 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 0C99776523200DE600EA0130 /* Project object */;
}


================================================
FILE: liGame/liGame.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:liGame.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: liGame/liGame.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IDEDidComputeMac32BitWarning</key>
	<true/>
</dict>
</plist>


================================================
FILE: liGame/liGame.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
   uuid = "C53C8EF3-EAAB-4A91-9ADC-B60CB1951A02"
   type = "1"
   version = "2.0">
   <Breakpoints>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "A5B13F0E-35B7-4822-9716-FBC061A7B51E"
            shouldBeEnabled = "No"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "liGame/ViewController.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "185"
            endingLineNumber = "185"
            landmarkName = "adsorb(_:)"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "7952585F-5F4C-4FF5-8CF8-A906DBFE5810"
            shouldBeEnabled = "No"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "liGame/ViewController.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "183"
            endingLineNumber = "183"
            landmarkName = "adsorb(_:)"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
   </Breakpoints>
</Bucket>


================================================
FILE: liGame/liGame.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>SchemeUserState</key>
	<dict>
		<key>liGame.xcscheme_^#shared#^_</key>
		<dict>
			<key>orderHint</key>
			<integer>0</integer>
		</dict>
	</dict>
</dict>
</plist>


================================================
FILE: liGame/liGame.xcodeproj/xcuserdata/wengpeijun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
   uuid = "A059B4AD-2C70-4238-AA7A-BE509499A88D"
   type = "1"
   version = "2.0">
   <Breakpoints>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "1177E8F8-EC69-44AA-84D5-D17FAD901AB7"
            shouldBeEnabled = "Yes"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "liGame/View/Bottom/LiBottomView.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "86"
            endingLineNumber = "86"
            landmarkName = "initView()"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "55E4E40E-0AFA-4A18-85CE-B52307385F98"
            shouldBeEnabled = "Yes"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "liGame/View/Bottom/LiBottomView.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "89"
            endingLineNumber = "89"
            landmarkName = "initView()"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "78B3E6D1-98F2-44CA-B0FD-3C22CA604D29"
            shouldBeEnabled = "Yes"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "liGame/View/Bottom/LiBottomView.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "92"
            endingLineNumber = "92"
            landmarkName = "initView()"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "40D5F9E4-9A58-4E3E-801D-C6C3ACED9611"
            shouldBeEnabled = "Yes"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "liGame/View/Bottom/LiBottomView.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "95"
            endingLineNumber = "95"
            landmarkName = "initView()"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
   </Breakpoints>
</Bucket>


================================================
FILE: liGame/liGame.xcodeproj/xcuserdata/wengpeijun.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>SchemeUserState</key>
	<dict>
		<key>liGame.xcscheme_^#shared#^_</key>
		<dict>
			<key>orderHint</key>
			<integer>0</integer>
		</dict>
	</dict>
</dict>
</plist>


================================================
FILE: lightGame/light-game/AppDelegate.swift
================================================
//
//  AppDelegate.swift
//  light-game
//
//  Created by pjhubs on 2019/8/29.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {



    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }


}



================================================
FILE: lightGame/light-game/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "3x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "83.5x83.5",
      "scale" : "2x"
    },
    {
      "idiom" : "ios-marketing",
      "size" : "1024x1024",
      "scale" : "1x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/light-game/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/light-game/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
</document>


================================================
FILE: lightGame/light-game/ContentView.swift
================================================
//
//  ContentView.swift
//  light-game
//
//  Created by pjhubs on 2019/8/29.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import SwiftUI

struct ContentView: View {    
    @ObservedObject var gameManager = GameManager(size: 5, lightSequence: [1, 2, 3])
    
    @State var isShowHistory = false
    
    var body: some View {
        VStack {
            HStack {
                Text("\(gameManager.timeString)")
                    .font(.system(size: 45))
                    
                Spacer()
                
                Text("\(gameManager.clickTimes)步")
                    .font(.system(size: 45))
                    
            }
                .padding(20)
                        
            ForEach(0..<gameManager.lights.count) { row in
                HStack(spacing: 20) {
                    ForEach(0..<self.gameManager.lights[row].count) { column in
                        Circle()
                            .foregroundColor(self.gameManager.lights[row][column].status ? .yellow : .gray)
                            .opacity(self.gameManager.lights[row][column].status ? 0.8 : 0.5)
                            .frame(width: self.gameManager.circleWidth(),
                                   height: self.gameManager.circleWidth())
                            .shadow(color: .yellow, radius: self.gameManager.lights[row][column].status ? 10 : 0)
                            .overlay(RoundedRectangle(cornerRadius: self.gameManager.lights[row][column].selected ? self.gameManager.circleWidth() : 0 ).stroke(Color.black, lineWidth: self.gameManager.lights[row][column].selected ? 5 : 0 ))
                            .onTapGesture {
                                self.gameManager.clickTimes += 1
                                self.gameManager.updateLightStatus(column: column, row: row, userTouch: true)
                        }
                    }
                }
                    .padding(EdgeInsets(top: 0, leading: 0, bottom: 20, trailing: 0))
            }
        }
            .alert(isPresented: $gameManager.isWin) {
                Alert(title: Text("黑灯瞎火,摸鱼成功!"), dismissButton: .default(Text("继续摸鱼"), action: {
                    self.gameManager.start([3, 2, 1])
                    self.gameManager.timerRestart()
                }))
        }
    }
}


================================================
FILE: lightGame/light-game/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UIApplicationSceneManifest</key>
	<dict>
		<key>UIApplicationSupportsMultipleScenes</key>
		<false/>
		<key>UISceneConfigurations</key>
		<dict>
			<key>UIWindowSceneSessionRoleApplication</key>
			<array>
				<dict>
					<key>UISceneConfigurationName</key>
					<string>Default Configuration</string>
					<key>UISceneDelegateClassName</key>
					<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
				</dict>
			</array>
		</dict>
	</dict>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: lightGame/light-game/Model/GameController.swift
================================================
//
//  GameController.swift
//  light-game
//
//  Created by 翁培钧 on 2019/11/30.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import GameController

class GameController {
    
    var movingX = false
    var movingY = false
    
    var isSelectX: ((Bool) -> ())?
    var isSelectY: ((Bool) -> ())?
    var isTapButtonA: (() -> ())?
    var isTapButtonB: (() -> ())?
    
    init() {
        NotificationCenter.default.addObserver(self, selector: .didConnect, name: .GCControllerDidConnect, object: nil)
        NotificationCenter.default.addObserver(self, selector: .didConnect, name: .GCControllerDidDisconnect, object: nil)
    }
}


extension GameController {
    @objc fileprivate func gameControllerDidConnect() {
        for controller in GCController.controllers() {
            if controller.extendedGamepad != nil {
                setupControllerControls(controller: controller)
            }
        }
    }
    
    @objc fileprivate func gameControllerDidDisconnect() {
        
    }
    
    func setupControllerControls(controller: GCController) {
        controller.extendedGamepad?.valueChangedHandler = {
            (gamepad: GCExtendedGamepad, element: GCControllerElement) in
            self.controllerInput(gamePad: gamepad, element: element)
        }
    }
    
    private func controllerInput(gamePad: GCExtendedGamepad, element: GCControllerElement) {
        // gamePad 为支持的类型,element 为当前手柄的输入
        // 不能 return,因为单次出发会带入多个按键的值
        
        if (gamePad.leftThumbstick == element) {
            if (gamePad.leftThumbstick.yAxis.value != 0 && !movingY && !movingX) {
                movingY = true
                isSelectY?(gamePad.leftThumbstick.yAxis.value > 0)
            } else if (gamePad.leftThumbstick.yAxis.value == 0) {
                movingY = false
            }
            
            if (gamePad.leftThumbstick.xAxis.value != 0 && !movingX && !movingY) {
                isSelectX?(gamePad.leftThumbstick.xAxis.value > 0)
                movingX = true
            } else if (gamePad.leftThumbstick.xAxis.value == 0) {
                movingX = false
            }
        } else if (gamePad.rightThumbstick == element) {
            if (gamePad.rightThumbstick.xAxis.value != 0) {
                print("rightThumbstickXAxis: \(gamePad.rightThumbstick.xAxis)")
            }
        } else if (gamePad.dpad == element) {
            if (gamePad.dpad.xAxis.value != 0) {
                isSelectX?(gamePad.dpad.xAxis.value > 0)
            } else if (gamePad.dpad.xAxis.value == 0) {
                
            }
            
            if (gamePad.dpad.yAxis.value != 0) {
                isSelectY?(gamePad.dpad.yAxis.value > 0)
            } else if (gamePad.dpad.yAxis.value == 0) {
                
            }
        } else if (gamePad.buttonA == element) {
            if (gamePad.buttonA.value != 0) {
                isTapButtonA?()
            }
        } else if (gamePad.buttonB == element) {
            if (gamePad.buttonB.value != 0) {
                isTapButtonB?()
            }
        } else if (gamePad.buttonY == element) {
            if (gamePad.buttonY.value != 0) {
//                print("Y-Button Pressed!")
//                buttonYTap = true
            }
        } else if (gamePad.buttonX == element) {
            if (gamePad.buttonX.value != 0) {
//                print("X-Button Pressed!")
//                buttonXTap = true
            }
        }
    }
}

private extension Selector {
    static let didConnect = #selector(GameController.gameControllerDidConnect)
    static let didDisConnect = #selector(GameController.gameControllerDidDisconnect)
}


================================================
FILE: lightGame/light-game/Model/GameManager.swift
================================================
//
//  GameManager.swift
//  light-game
//
//  Created by pjhubs on 2019/8/30.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import SwiftUI
import Combine

class GameManager: ObservableObject {
    /// 对外发布的格式化计时器字符串
    @Published var timeString = "00:00"
    /// 点击次数
    @Published var clickTimes = 0
    /// 灯状态
    @Published var lights = [[Light]]()
    @Published var isWin = false
    /// 当前游戏状态
    private var currentStatus: GameStatus = .during {
        didSet {
            switch currentStatus {
            case .win: isWin = true
            case .lose: isWin = false
            case .during: break
            }
        }
    }
    
    /// 游戏尺寸大小
    private(set) var size: Int?
    /// 游戏计时器
    private var timer: Timer?
    /// 游戏持续时间
    private var durations = 1
    private var gameController = GameController()
    private var row = 0
    private var column = 0
    private var pRow = 0
    private var pColumn = 0
    
    /// 游戏控制器暂停
    private var isPause = false
    
    // MARK: - Init
    
    /// 便捷构造方法
    /// - Parameters:
    ///   - size: 游戏布局尺寸,默认值 5x5
    ///   - lightSequence: 亮灯序列,默认全灭
    convenience init(size: Int = 5,
                     lightSequence: [Int] = [Int]()) {
        
        self.init()
        
        var size = size
        // 太大了不好玩
        if size > 8 {
            size = 7
        }
        // 太小了没意思
        if size < 2 {
            size = 2
        }
        self.size = size
        lights = Array(repeating: Array(repeating: Light(), count: size), count: size)
        
        initGameController()
        start(lightSequence)
    }
    
    // MARK: Public
    
    /// 游戏配置
    /// - Parameter lightSequence: 亮灯序列
    func start(_ lightSequence: [Int]) {
        currentStatus = .during
        clickTimes = 0
        updateLightStatus(lightSequence)
        
        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { timer in
            let min = self.durations >= 60 ? self.durations / 60 : 0
            let seconds = self.durations - min * 60
            
            
            let minString = min >= 10 ? "\(min)" : "0\(min)"
            let secondString = self.durations - min * 60 >= 10 ? "\(seconds)" : "0\(seconds)"
            self.timeString = minString + ":" + secondString
            
            self.durations += 1
        })
    }
    
    /// 停止
    func timerStop() {
        timer?.fireDate = Date.distantFuture
    }
    
    /// 重新创建
    func timerRestart() {
        isPause = false
        durations = 0
        timeString = "00:00"
        timer?.fireDate = Date()
    }
    
    /// 获取灯的尺寸
    func circleWidth() -> CGFloat {
        guard let size = size else { return 0 }
        
        /// 距离屏幕左右两边的间距
        let padding: CGFloat = 20
        /// 左右两灯之间的间距
        let innerSpacing: CGFloat = 20
        
        var circleWidth = (UIScreen.main.bounds.width - padding - (CGFloat(size) * innerSpacing)) / CGFloat(size)
        
        // 太大了会很丑,过滤下
        if circleWidth > UIScreen.main.bounds.width / 5 {
            circleWidth = UIScreen.main.bounds.width / 5
        }
    
        return circleWidth
    }
    
    /// 通过坐标索引修改灯状态
    /// - Parameters:
    ///   - column: 灯-列索引
    ///   - size: 灯-行索引
    func updateLightStatus(column: Int, row: Int, userTouch: Bool) {
        lights[row][column].status.toggle()
        self.column = row
        self.row = column
        
        // 上
        let top = row - 1
        if !(top < 0) {
            lights[top][column].status.toggle()
        }
        // 下
        let bottom = row + 1
        if !(bottom > lights.count - 1) {
            lights[bottom][column].status.toggle()
        }
        // 左
        let left = column - 1
        if !(left < 0) {
            lights[row][left].status.toggle()
        }
        // 右
        let right = column + 1
        if !(right > lights.count - 1) {
            lights[row][right].status.toggle()
        }
        
        updateGameStatus()
        
        if (userTouch) {
            disSelectedGameControllerStatus()
        }
    }
    
    // MARK: Private
    
    /// 通过亮灯序列修改灯状态
    /// - Parameter lightSequence: 亮灯序列
    private func updateLightStatus(_ lightSequence: [Int]) {
        guard let size = size else { return }
        for lightIndex in lightSequence {
            var index = lightIndex
            // 防止数组越出最大边界处
            if index >= size * size {
                index = size * size - 1
            }
            let row = lightIndex / size
            let column = lightIndex % size
            // column 不为 0,说明非最后一个
            // row 为 0,说明为第一行
            updateLightStatus(column: column, row: row, userTouch: true)
        }
    }
    
    private func updateLightSelected() {
        lights[pColumn][pRow].selected = false
        lights[column][row].selected = true
        
        pRow = row
        pColumn = column
    }
    
    private func disSelectedGameControllerStatus() {
        lights[pColumn][pRow].selected = false
    }
    
    /// 判赢
    private func updateGameStatus() {
        guard let size = size else { return }
        
        var lightingCount = 0
        
        
        for lightArr in lights {
            for light in lightArr {
                if light.status { lightingCount += 1 }
            }
        }
        
        if lightingCount == size * size {
            timerStop()
            currentStatus = .lose
            return
        }
        
        if lightingCount == 0 {
            timerStop()
            currentStatus = .win
            isPause = true
            return
        }
    }
    
    private func initGameController() {
        gameController.isSelectX = {
            guard !self.isPause else { return }
            
            if $0 {
                if (self.row < self.lights.count - 1) {
                    self.row += 1
                }
            } else {
                if self.row > 0 {
                    self.row -= 1
                }
            }
            
            self.updateLightSelected()
        }
        
        gameController.isSelectY = {
            guard !self.isPause else { return }
            
            if $0 {
                if (self.column > 0) {
                    self.column -= 1
                }
            } else {
                if (self.column < self.lights.count - 1) {
                    self.column += 1
                }
            }
            
            self.updateLightSelected()
        }
        
        gameController.isTapButtonA = {
            self.clickTimes += 1
            self.updateLightStatus(column: self.row, row: self.column, userTouch: false)
        }
    }
}

extension GameManager {
    enum GameStatus {
        /// 赢
        case win
        /// 输
        case lose
        /// 进行中
        case during
    }
}


================================================
FILE: lightGame/light-game/Model/Light.swift
================================================
//
//  Light.swift
//  light-game
//
//  Created by pjhubs on 2019/8/29.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import Foundation

struct Light {
    /// 开关状态
    var status = false
    
    /// 选中状态
    var selected = false
}


================================================
FILE: lightGame/light-game/Preview Content/Preview Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/light-game/SceneDelegate.swift
================================================
//
//  SceneDelegate.swift
//  light-game
//
//  Created by pjhubs on 2019/8/29.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import UIKit
import SwiftUI

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

        // Create the SwiftUI view that provides the window contents.
        #if !os(watchOS)
            let contentView = ContentView()
        #else
            let contentView = WatchContentView()
        #endif

        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }

    func sceneDidDisconnect(_ scene: UIScene) {
        // Called as the scene is being released by the system.
        // This occurs shortly after the scene enters the background, or when its session is discarded.
        // Release any resources associated with this scene that can be re-created the next time the scene connects.
        // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        // Called when the scene has moved from an inactive state to an active state.
        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
    }

    func sceneWillResignActive(_ scene: UIScene) {
        // Called when the scene will move from an active state to an inactive state.
        // This may occur due to temporary interruptions (ex. an incoming phone call).
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        // Called as the scene transitions from the foreground to the background.
        // Use this method to save data, release shared resources, and store enough scene-specific state information
        // to restore the scene back to its current state.
    }


}



================================================
FILE: lightGame/light-game.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 50;
	objects = {

/* Begin PBXBuildFile section */
		0C39CB06239BEF1100444729 /* Light.swift in Sources */ = {isa = PBXBuildFile; fileRef = A601DB2A2317775100327867 /* Light.swift */; };
		0C39CB0B239BF2EE00444729 /* WatchGameManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C39CB0A239BF2EE00444729 /* WatchGameManager.swift */; };
		0C39CB0D239C020000444729 /* WatchContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C39CB0C239C020000444729 /* WatchContentView.swift */; };
		0C3DCCE42392A5CC00C762A9 /* GameController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C3DCCE32392A5CC00C762A9 /* GameController.swift */; };
		0C751029239BEAA500E85E20 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0C751027239BEAA500E85E20 /* Interface.storyboard */; };
		0C75102B239BEAA800E85E20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0C75102A239BEAA800E85E20 /* Assets.xcassets */; };
		0C751032239BEAA900E85E20 /* watchapp Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0C751031239BEAA900E85E20 /* watchapp Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
		0C751039239BEAA900E85E20 /* HostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C751038239BEAA900E85E20 /* HostingController.swift */; };
		0C75103B239BEAA900E85E20 /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C75103A239BEAA900E85E20 /* ExtensionDelegate.swift */; };
		0C75103D239BEAA900E85E20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0C75103C239BEAA900E85E20 /* Assets.xcassets */; };
		0C751040239BEAA900E85E20 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0C75103F239BEAA900E85E20 /* Preview Assets.xcassets */; };
		0C751044239BEAA900E85E20 /* watchapp.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 0C751025239BEAA500E85E20 /* watchapp.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
		A601DB2B2317775100327867 /* Light.swift in Sources */ = {isa = PBXBuildFile; fileRef = A601DB2A2317775100327867 /* Light.swift */; };
		A62D002F231904F80062A70E /* GameManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A62D002E231904F80062A70E /* GameManager.swift */; };
		A676EA93231771D3002074BF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A676EA92231771D3002074BF /* AppDelegate.swift */; };
		A676EA95231771D3002074BF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A676EA94231771D3002074BF /* SceneDelegate.swift */; };
		A676EA97231771D3002074BF /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A676EA96231771D3002074BF /* ContentView.swift */; };
		A676EA99231771D5002074BF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A676EA98231771D5002074BF /* Assets.xcassets */; };
		A676EA9C231771D5002074BF /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A676EA9B231771D5002074BF /* Preview Assets.xcassets */; };
		A676EA9F231771D5002074BF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A676EA9D231771D5002074BF /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		0C751033239BEAA900E85E20 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = A676EA87231771D2002074BF /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = 0C751030239BEAA900E85E20;
			remoteInfo = "watchapp Extension";
		};
		0C751042239BEAA900E85E20 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = A676EA87231771D2002074BF /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = 0C751024239BEAA500E85E20;
			remoteInfo = watchapp;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
		0C751045239BEAA900E85E20 /* Embed Watch Content */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 2147483647;
			dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
			dstSubfolderSpec = 16;
			files = (
				0C751044239BEAA900E85E20 /* watchapp.app in Embed Watch Content */,
			);
			name = "Embed Watch Content";
			runOnlyForDeploymentPostprocessing = 0;
		};
		0C751048239BEAA900E85E20 /* Embed App Extensions */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 2147483647;
			dstPath = "";
			dstSubfolderSpec = 13;
			files = (
				0C751032239BEAA900E85E20 /* watchapp Extension.appex in Embed App Extensions */,
			);
			name = "Embed App Extensions";
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
		0C39CB0A239BF2EE00444729 /* WatchGameManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchGameManager.swift; sourceTree = "<group>"; };
		0C39CB0C239C020000444729 /* WatchContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchContentView.swift; sourceTree = "<group>"; };
		0C3DCCE32392A5CC00C762A9 /* GameController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameController.swift; sourceTree = "<group>"; };
		0C751025239BEAA500E85E20 /* watchapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = watchapp.app; sourceTree = BUILT_PRODUCTS_DIR; };
		0C751028239BEAA500E85E20 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = "<group>"; };
		0C75102A239BEAA800E85E20 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		0C75102C239BEAA800E85E20 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		0C751031239BEAA900E85E20 /* watchapp Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "watchapp Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
		0C751038239BEAA900E85E20 /* HostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingController.swift; sourceTree = "<group>"; };
		0C75103A239BEAA900E85E20 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = "<group>"; };
		0C75103C239BEAA900E85E20 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		0C75103F239BEAA900E85E20 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
		0C751041239BEAA900E85E20 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		A601DB2A2317775100327867 /* Light.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Light.swift; sourceTree = "<group>"; };
		A62D002E231904F80062A70E /* GameManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameManager.swift; sourceTree = "<group>"; };
		A676EA8F231771D3002074BF /* light-game.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "light-game.app"; sourceTree = BUILT_PRODUCTS_DIR; };
		A676EA92231771D3002074BF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
		A676EA94231771D3002074BF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
		A676EA96231771D3002074BF /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
		A676EA98231771D5002074BF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		A676EA9B231771D5002074BF /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
		A676EA9E231771D5002074BF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
		A676EAA0231771D5002074BF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		0C75102E239BEAA900E85E20 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		A676EA8C231771D2002074BF /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		0C751026239BEAA500E85E20 /* watchapp */ = {
			isa = PBXGroup;
			children = (
				0C751027239BEAA500E85E20 /* Interface.storyboard */,
				0C75102A239BEAA800E85E20 /* Assets.xcassets */,
				0C75102C239BEAA800E85E20 /* Info.plist */,
			);
			path = watchapp;
			sourceTree = "<group>";
		};
		0C751035239BEAA900E85E20 /* watchapp Extension */ = {
			isa = PBXGroup;
			children = (
				0C751038239BEAA900E85E20 /* HostingController.swift */,
				0C39CB0C239C020000444729 /* WatchContentView.swift */,
				0C39CB0A239BF2EE00444729 /* WatchGameManager.swift */,
				0C75103A239BEAA900E85E20 /* ExtensionDelegate.swift */,
				0C75103C239BEAA900E85E20 /* Assets.xcassets */,
				0C751041239BEAA900E85E20 /* Info.plist */,
				0C75103E239BEAA900E85E20 /* Preview Content */,
			);
			path = "watchapp Extension";
			sourceTree = "<group>";
		};
		0C75103E239BEAA900E85E20 /* Preview Content */ = {
			isa = PBXGroup;
			children = (
				0C75103F239BEAA900E85E20 /* Preview Assets.xcassets */,
			);
			path = "Preview Content";
			sourceTree = "<group>";
		};
		A601DB292317774600327867 /* Model */ = {
			isa = PBXGroup;
			children = (
				A601DB2A2317775100327867 /* Light.swift */,
				A62D002E231904F80062A70E /* GameManager.swift */,
				0C3DCCE32392A5CC00C762A9 /* GameController.swift */,
			);
			path = Model;
			sourceTree = "<group>";
		};
		A676EA86231771D2002074BF = {
			isa = PBXGroup;
			children = (
				A676EA91231771D3002074BF /* light-game */,
				0C751026239BEAA500E85E20 /* watchapp */,
				0C751035239BEAA900E85E20 /* watchapp Extension */,
				A676EA90231771D3002074BF /* Products */,
			);
			sourceTree = "<group>";
		};
		A676EA90231771D3002074BF /* Products */ = {
			isa = PBXGroup;
			children = (
				A676EA8F231771D3002074BF /* light-game.app */,
				0C751025239BEAA500E85E20 /* watchapp.app */,
				0C751031239BEAA900E85E20 /* watchapp Extension.appex */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		A676EA91231771D3002074BF /* light-game */ = {
			isa = PBXGroup;
			children = (
				A676EA92231771D3002074BF /* AppDelegate.swift */,
				A676EA94231771D3002074BF /* SceneDelegate.swift */,
				A676EA96231771D3002074BF /* ContentView.swift */,
				A601DB292317774600327867 /* Model */,
				A676EA98231771D5002074BF /* Assets.xcassets */,
				A676EA9D231771D5002074BF /* LaunchScreen.storyboard */,
				A676EAA0231771D5002074BF /* Info.plist */,
				A676EA9A231771D5002074BF /* Preview Content */,
			);
			path = "light-game";
			sourceTree = "<group>";
		};
		A676EA9A231771D5002074BF /* Preview Content */ = {
			isa = PBXGroup;
			children = (
				A676EA9B231771D5002074BF /* Preview Assets.xcassets */,
			);
			path = "Preview Content";
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		0C751024239BEAA500E85E20 /* watchapp */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 0C75104C239BEAA900E85E20 /* Build configuration list for PBXNativeTarget "watchapp" */;
			buildPhases = (
				0C751023239BEAA500E85E20 /* Resources */,
				0C751048239BEAA900E85E20 /* Embed App Extensions */,
			);
			buildRules = (
			);
			dependencies = (
				0C751034239BEAA900E85E20 /* PBXTargetDependency */,
			);
			name = watchapp;
			productName = watchapp;
			productReference = 0C751025239BEAA500E85E20 /* watchapp.app */;
			productType = "com.apple.product-type.application.watchapp2";
		};
		0C751030239BEAA900E85E20 /* watchapp Extension */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 0C75104B239BEAA900E85E20 /* Build configuration list for PBXNativeTarget "watchapp Extension" */;
			buildPhases = (
				0C75102D239BEAA900E85E20 /* Sources */,
				0C75102E239BEAA900E85E20 /* Frameworks */,
				0C75102F239BEAA900E85E20 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = "watchapp Extension";
			productName = "watchapp Extension";
			productReference = 0C751031239BEAA900E85E20 /* watchapp Extension.appex */;
			productType = "com.apple.product-type.watchkit2-extension";
		};
		A676EA8E231771D2002074BF /* light-game */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = A676EAA3231771D5002074BF /* Build configuration list for PBXNativeTarget "light-game" */;
			buildPhases = (
				A676EA8B231771D2002074BF /* Sources */,
				A676EA8C231771D2002074BF /* Frameworks */,
				A676EA8D231771D2002074BF /* Resources */,
				0C751045239BEAA900E85E20 /* Embed Watch Content */,
			);
			buildRules = (
			);
			dependencies = (
				0C751043239BEAA900E85E20 /* PBXTargetDependency */,
			);
			name = "light-game";
			productName = "light-game";
			productReference = A676EA8F231771D3002074BF /* light-game.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		A676EA87231771D2002074BF /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastSwiftUpdateCheck = 1120;
				LastUpgradeCheck = 1100;
				ORGANIZATIONNAME = PJHubs;
				TargetAttributes = {
					0C751024239BEAA500E85E20 = {
						CreatedOnToolsVersion = 11.2.1;
					};
					0C751030239BEAA900E85E20 = {
						CreatedOnToolsVersion = 11.2.1;
					};
					A676EA8E231771D2002074BF = {
						CreatedOnToolsVersion = 11.0;
					};
				};
			};
			buildConfigurationList = A676EA8A231771D2002074BF /* Build configuration list for PBXProject "light-game" */;
			compatibilityVersion = "Xcode 9.3";
			developmentRegion = en;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = A676EA86231771D2002074BF;
			productRefGroup = A676EA90231771D3002074BF /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				A676EA8E231771D2002074BF /* light-game */,
				0C751024239BEAA500E85E20 /* watchapp */,
				0C751030239BEAA900E85E20 /* watchapp Extension */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		0C751023239BEAA500E85E20 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				0C75102B239BEAA800E85E20 /* Assets.xcassets in Resources */,
				0C751029239BEAA500E85E20 /* Interface.storyboard in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		0C75102F239BEAA900E85E20 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				0C751040239BEAA900E85E20 /* Preview Assets.xcassets in Resources */,
				0C75103D239BEAA900E85E20 /* Assets.xcassets in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		A676EA8D231771D2002074BF /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				A676EA9F231771D5002074BF /* LaunchScreen.storyboard in Resources */,
				A676EA9C231771D5002074BF /* Preview Assets.xcassets in Resources */,
				A676EA99231771D5002074BF /* Assets.xcassets in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		0C75102D239BEAA900E85E20 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				0C751039239BEAA900E85E20 /* HostingController.swift in Sources */,
				0C39CB0B239BF2EE00444729 /* WatchGameManager.swift in Sources */,
				0C39CB0D239C020000444729 /* WatchContentView.swift in Sources */,
				0C39CB06239BEF1100444729 /* Light.swift in Sources */,
				0C75103B239BEAA900E85E20 /* ExtensionDelegate.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		A676EA8B231771D2002074BF /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				A676EA93231771D3002074BF /* AppDelegate.swift in Sources */,
				0C3DCCE42392A5CC00C762A9 /* GameController.swift in Sources */,
				A676EA95231771D3002074BF /* SceneDelegate.swift in Sources */,
				A601DB2B2317775100327867 /* Light.swift in Sources */,
				A676EA97231771D3002074BF /* ContentView.swift in Sources */,
				A62D002F231904F80062A70E /* GameManager.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
		0C751034239BEAA900E85E20 /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = 0C751030239BEAA900E85E20 /* watchapp Extension */;
			targetProxy = 0C751033239BEAA900E85E20 /* PBXContainerItemProxy */;
		};
		0C751043239BEAA900E85E20 /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = 0C751024239BEAA500E85E20 /* watchapp */;
			targetProxy = 0C751042239BEAA900E85E20 /* PBXContainerItemProxy */;
		};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
		0C751027239BEAA500E85E20 /* Interface.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				0C751028239BEAA500E85E20 /* Base */,
			);
			name = Interface.storyboard;
			sourceTree = "<group>";
		};
		A676EA9D231771D5002074BF /* LaunchScreen.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				A676EA9E231771D5002074BF /* Base */,
			);
			name = LaunchScreen.storyboard;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		0C751046239BEAA900E85E20 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = U6J5965DZK;
				IBSC_MODULE = watchapp_Extension;
				INFOPLIST_FILE = watchapp/Info.plist;
				PRODUCT_BUNDLE_IDENTIFIER = "com.pjhubs.light-game.watchkitapp";
				PRODUCT_NAME = "$(TARGET_NAME)";
				SDKROOT = watchos;
				SKIP_INSTALL = YES;
				SWIFT_VERSION = 5.0;
				TARGETED_DEVICE_FAMILY = 4;
				WATCHOS_DEPLOYMENT_TARGET = 6.1;
			};
			name = Debug;
		};
		0C751047239BEAA900E85E20 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = U6J5965DZK;
				IBSC_MODULE = watchapp_Extension;
				INFOPLIST_FILE = watchapp/Info.plist;
				PRODUCT_BUNDLE_IDENTIFIER = "com.pjhubs.light-game.watchkitapp";
				PRODUCT_NAME = "$(TARGET_NAME)";
				SDKROOT = watchos;
				SKIP_INSTALL = YES;
				SWIFT_VERSION = 5.0;
				TARGETED_DEVICE_FAMILY = 4;
				WATCHOS_DEPLOYMENT_TARGET = 6.1;
			};
			name = Release;
		};
		0C751049239BEAA900E85E20 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_ASSET_PATHS = "\"watchapp Extension/Preview Content\"";
				DEVELOPMENT_TEAM = U6J5965DZK;
				ENABLE_PREVIEWS = YES;
				INFOPLIST_FILE = "watchapp Extension/Info.plist";
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
					"@executable_path/../../Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = "com.pjhubs.light-game.watchkitapp.watchkitextension";
				PRODUCT_NAME = "${TARGET_NAME}";
				SDKROOT = watchos;
				SKIP_INSTALL = YES;
				SWIFT_VERSION = 5.0;
				TARGETED_DEVICE_FAMILY = 4;
				WATCHOS_DEPLOYMENT_TARGET = 6.1;
			};
			name = Debug;
		};
		0C75104A239BEAA900E85E20 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_ASSET_PATHS = "\"watchapp Extension/Preview Content\"";
				DEVELOPMENT_TEAM = U6J5965DZK;
				ENABLE_PREVIEWS = YES;
				INFOPLIST_FILE = "watchapp Extension/Info.plist";
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
					"@executable_path/../../Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = "com.pjhubs.light-game.watchkitapp.watchkitextension";
				PRODUCT_NAME = "${TARGET_NAME}";
				SDKROOT = watchos;
				SKIP_INSTALL = YES;
				SWIFT_VERSION = 5.0;
				TARGETED_DEVICE_FAMILY = 4;
				WATCHOS_DEPLOYMENT_TARGET = 6.1;
			};
			name = Release;
		};
		A676EAA1231771D5002074BF /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_ENABLE_OBJC_WEAK = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu11;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
				MTL_FAST_MATH = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
			};
			name = Debug;
		};
		A676EAA2231771D5002074BF /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_ENABLE_OBJC_WEAK = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu11;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				MTL_FAST_MATH = YES;
				SDKROOT = iphoneos;
				SWIFT_COMPILATION_MODE = wholemodule;
				SWIFT_OPTIMIZATION_LEVEL = "-O";
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		A676EAA4231771D5002074BF /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_ASSET_PATHS = "\"light-game/Preview Content\"";
				DEVELOPMENT_TEAM = U6J5965DZK;
				ENABLE_PREVIEWS = YES;
				INFOPLIST_FILE = "light-game/Info.plist";
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = "com.pjhubs.light-game";
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5.0;
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		A676EAA5231771D5002074BF /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_ASSET_PATHS = "\"light-game/Preview Content\"";
				DEVELOPMENT_TEAM = U6J5965DZK;
				ENABLE_PREVIEWS = YES;
				INFOPLIST_FILE = "light-game/Info.plist";
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = "com.pjhubs.light-game";
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5.0;
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		0C75104B239BEAA900E85E20 /* Build configuration list for PBXNativeTarget "watchapp Extension" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				0C751049239BEAA900E85E20 /* Debug */,
				0C75104A239BEAA900E85E20 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		0C75104C239BEAA900E85E20 /* Build configuration list for PBXNativeTarget "watchapp" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				0C751046239BEAA900E85E20 /* Debug */,
				0C751047239BEAA900E85E20 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		A676EA8A231771D2002074BF /* Build configuration list for PBXProject "light-game" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				A676EAA1231771D5002074BF /* Debug */,
				A676EAA2231771D5002074BF /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		A676EAA3231771D5002074BF /* Build configuration list for PBXNativeTarget "light-game" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				A676EAA4231771D5002074BF /* Debug */,
				A676EAA5231771D5002074BF /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = A676EA87231771D2002074BF /* Project object */;
}


================================================
FILE: lightGame/light-game.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:light-game.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: lightGame/light-game.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IDEDidComputeMac32BitWarning</key>
	<true/>
</dict>
</plist>


================================================
FILE: lightGame/light-game.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
   uuid = "1E1C8DCA-4FD3-4651-B05E-8AE053F638C6"
   type = "1"
   version = "2.0">
   <Breakpoints>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "610E61EB-F981-4607-9600-C4AD0106CE62"
            shouldBeEnabled = "No"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "light-game/Model/GameManager.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "193"
            endingLineNumber = "193"
            landmarkName = "disSelectedGameControllerStatus()"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "2B2D5D59-5599-4E4F-A239-57736FACA039"
            shouldBeEnabled = "No"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "light-game/Model/GameController.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "71"
            endingLineNumber = "71"
            landmarkName = "controllerInput(gamePad:element:)"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "1D26BA74-F3FE-48DE-A097-4C9C3CCC5024"
            shouldBeEnabled = "No"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "light-game/Model/GameController.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "52"
            endingLineNumber = "52"
            landmarkName = "controllerInput(gamePad:element:)"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
      <BreakpointProxy
         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
         <BreakpointContent
            uuid = "8F94D89E-687E-4D1E-ABCC-FFFFB815A3F3"
            shouldBeEnabled = "No"
            ignoreCount = "0"
            continueAfterRunningActions = "No"
            filePath = "light-game/Model/GameController.swift"
            startingColumnNumber = "9223372036854775807"
            endingColumnNumber = "9223372036854775807"
            startingLineNumber = "67"
            endingLineNumber = "67"
            landmarkName = "controllerInput(gamePad:element:)"
            landmarkType = "7">
         </BreakpointContent>
      </BreakpointProxy>
   </Breakpoints>
</Bucket>


================================================
FILE: lightGame/light-game.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>SchemeUserState</key>
	<dict>
		<key>light-game.xcscheme_^#shared#^_</key>
		<dict>
			<key>orderHint</key>
			<integer>0</integer>
		</dict>
		<key>watchapp.xcscheme_^#shared#^_</key>
		<dict>
			<key>orderHint</key>
			<integer>1</integer>
		</dict>
	</dict>
</dict>
</plist>


================================================
FILE: lightGame/light-game.xcodeproj/xcuserdata/wengpeijun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
   uuid = "9170105D-1022-4B15-93E6-44F08E915BF2"
   type = "1"
   version = "2.0">
</Bucket>


================================================
FILE: lightGame/light-game.xcodeproj/xcuserdata/wengpeijun.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>SchemeUserState</key>
	<dict>
		<key>light-game.xcscheme_^#shared#^_</key>
		<dict>
			<key>orderHint</key>
			<integer>0</integer>
		</dict>
	</dict>
</dict>
</plist>


================================================
FILE: lightGame/watchapp/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "size" : "24x24",
      "idiom" : "watch",
      "scale" : "2x",
      "role" : "notificationCenter",
      "subtype" : "38mm"
    },
    {
      "size" : "27.5x27.5",
      "idiom" : "watch",
      "scale" : "2x",
      "role" : "notificationCenter",
      "subtype" : "42mm"
    },
    {
      "size" : "29x29",
      "idiom" : "watch",
      "role" : "companionSettings",
      "scale" : "2x"
    },
    {
      "size" : "29x29",
      "idiom" : "watch",
      "role" : "companionSettings",
      "scale" : "3x"
    },
    {
      "size" : "40x40",
      "idiom" : "watch",
      "scale" : "2x",
      "role" : "appLauncher",
      "subtype" : "38mm"
    },
    {
      "size" : "44x44",
      "idiom" : "watch",
      "scale" : "2x",
      "role" : "appLauncher",
      "subtype" : "40mm"
    },
    {
      "size" : "50x50",
      "idiom" : "watch",
      "scale" : "2x",
      "role" : "appLauncher",
      "subtype" : "44mm"
    },
    {
      "size" : "86x86",
      "idiom" : "watch",
      "scale" : "2x",
      "role" : "quickLook",
      "subtype" : "38mm"
    },
    {
      "size" : "98x98",
      "idiom" : "watch",
      "scale" : "2x",
      "role" : "quickLook",
      "subtype" : "42mm"
    },
    {
      "size" : "108x108",
      "idiom" : "watch",
      "scale" : "2x",
      "role" : "quickLook",
      "subtype" : "44mm"
    },
    {
      "idiom" : "watch-marketing",
      "size" : "1024x1024",
      "scale" : "1x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp/Base.lproj/Interface.storyboard
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="15505" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="3mp-fW-waa">
    <device id="watch38"/>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15510"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="15501"/>
    </dependencies>
    <scenes>
        <!--Hosting Controller-->
        <scene sceneID="aou-V4-d1y">
            <objects>
                <hostingController id="3mp-fW-waa" customClass="HostingController" customModule="watchapp" customModuleProvider="target"/>
            </objects>
            <point key="canvasLocation" x="34" y="31"/>
        </scene>
    </scenes>
</document>


================================================
FILE: lightGame/watchapp/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleDisplayName</key>
	<string>light-game</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
	</array>
	<key>WKCompanionAppBundleIdentifier</key>
	<string>com.pjhubs.light-game</string>
	<key>WKWatchKitApp</key>
	<true/>
</dict>
</plist>


================================================
FILE: lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : "<=145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">161"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">183"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Contents.json
================================================
{
  "assets" : [
    {
      "idiom" : "watch",
      "filename" : "Circular.imageset",
      "role" : "circular"
    },
    {
      "idiom" : "watch",
      "filename" : "Extra Large.imageset",
      "role" : "extra-large"
    },
    {
      "idiom" : "watch",
      "filename" : "Graphic Bezel.imageset",
      "role" : "graphic-bezel"
    },
    {
      "idiom" : "watch",
      "filename" : "Graphic Circular.imageset",
      "role" : "graphic-circular"
    },
    {
      "idiom" : "watch",
      "filename" : "Graphic Corner.imageset",
      "role" : "graphic-corner"
    },
    {
      "idiom" : "watch",
      "filename" : "Graphic Large Rectangular.imageset",
      "role" : "graphic-large-rectangular"
    },
    {
      "idiom" : "watch",
      "filename" : "Modular.imageset",
      "role" : "modular"
    },
    {
      "idiom" : "watch",
      "filename" : "Utilitarian.imageset",
      "role" : "utilitarian"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : "<=145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">161"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">183"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : "<=145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">161"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">183"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : "<=145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">161"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">183"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : "<=145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">161"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">183"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : "<=145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">161"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">183"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : "<=145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">161"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">183"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : "<=145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">161"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">145"
    },
    {
      "idiom" : "watch",
      "scale" : "2x",
      "screen-width" : ">183"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/ExtensionDelegate.swift
================================================
//
//  ExtensionDelegate.swift
//  watchapp Extension
//
//  Created by 翁培钧 on 2019/12/7.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import WatchKit

class ExtensionDelegate: NSObject, WKExtensionDelegate {

    func applicationDidFinishLaunching() {
        // Perform any final initialization of your application.
    }

    func applicationDidBecomeActive() {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillResignActive() {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, etc.
    }

    func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
        // Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one.
        for task in backgroundTasks {
            // Use a switch statement to check the task type
            switch task {
            case let backgroundTask as WKApplicationRefreshBackgroundTask:
                // Be sure to complete the background task once you’re done.
                backgroundTask.setTaskCompletedWithSnapshot(false)
            case let snapshotTask as WKSnapshotRefreshBackgroundTask:
                // Snapshot tasks have a unique completion call, make sure to set your expiration date
                snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil)
            case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask:
                // Be sure to complete the connectivity task once you’re done.
                connectivityTask.setTaskCompletedWithSnapshot(false)
            case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
                // Be sure to complete the URL session task once you’re done.
                urlSessionTask.setTaskCompletedWithSnapshot(false)
            case let relevantShortcutTask as WKRelevantShortcutRefreshBackgroundTask:
                // Be sure to complete the relevant-shortcut task once you're done.
                relevantShortcutTask.setTaskCompletedWithSnapshot(false)
            case let intentDidRunTask as WKIntentDidRunRefreshBackgroundTask:
                // Be sure to complete the intent-did-run task once you're done.
                intentDidRunTask.setTaskCompletedWithSnapshot(false)
            default:
                // make sure to complete unhandled task types
                task.setTaskCompletedWithSnapshot(false)
            }
        }
    }

}


================================================
FILE: lightGame/watchapp Extension/HostingController.swift
================================================
//
//  HostingController.swift
//  watchapp Extension
//
//  Created by 翁培钧 on 2019/12/7.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import WatchKit
import Foundation
import SwiftUI

class HostingController: WKHostingController<ContentView> {
    override var body: ContentView {
        return ContentView()
    }
}


================================================
FILE: lightGame/watchapp Extension/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleDisplayName</key>
	<string>watchapp Extension</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>NSExtension</key>
	<dict>
		<key>NSExtensionAttributes</key>
		<dict>
			<key>WKAppBundleIdentifier</key>
			<string>com.pjhubs.light-game.watchkitapp</string>
		</dict>
		<key>NSExtensionPointIdentifier</key>
		<string>com.apple.watchkit</string>
	</dict>
	<key>WKExtensionDelegateClassName</key>
	<string>$(PRODUCT_MODULE_NAME).ExtensionDelegate</string>
	<key>WKRunsIndependentlyOfCompanionApp</key>
	<true/>
</dict>
</plist>


================================================
FILE: lightGame/watchapp Extension/Preview Content/Preview Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: lightGame/watchapp Extension/WatchContentView.swift
================================================
//
//  WatchContentView.swift
//  watchapp Extension
//
//  Created by 翁培钧 on 2019/12/7.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import SwiftUI

struct ContentView: View {
    @ObservedObject var gameManager = WatchGameManager(size: 3, lightSequence: [1, 2, 3])
    
    @State var isShowHistory = false
    
    var body: some View {
        VStack {
            ForEach(0..<gameManager.lights.count) { row in
                HStack {
                    ForEach(0..<self.gameManager.lights[row].count) { column in
                        Circle()
                            .foregroundColor(self.gameManager.lights[row][column].status ? .yellow : .gray)
                            .opacity(self.gameManager.lights[row][column].status ? 0.8 : 0.5)
                            .frame(width: self.gameManager.circleWidth(),
                                   height: self.gameManager.circleWidth())
                            .shadow(color: .yellow, radius: self.gameManager.lights[row][column].status ? 10 : 0)
                            .padding(10)
                            .overlay(RoundedRectangle(cornerRadius: self.gameManager.lights[row][column].selected ? self.gameManager.circleWidth() : 0 ).stroke(Color.black, lineWidth: self.gameManager.lights[row][column].selected ? 5 : 0 ))
                            .onTapGesture {
                                self.gameManager.clickTimes += 1
                                self.gameManager.updateLightStatus(column: column, row: row, userTouch: true)
                        }
                    }
                }
            }
        }
            .alert(isPresented: $gameManager.isWin) {
                Alert(title: Text("黑灯瞎火,摸鱼成功!"), dismissButton: .default(Text("继续摸鱼"), action: {
                    self.gameManager.start([3, 2, 1])
                    self.gameManager.timerRestart()
                }))
        }
    }
}


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


================================================
FILE: lightGame/watchapp Extension/WatchGameManager.swift
================================================
//
//  WatchGameManager.swift
//  watchapp Extension
//
//  Created by 翁培钧 on 2019/12/7.
//  Copyright © 2019 PJHubs. All rights reserved.
//

import SwiftUI
import Combine

class WatchGameManager: ObservableObject {
    /// 对外发布的格式化计时器字符串
    @Published var timeString = "00:00"
    /// 点击次数
    @Published var clickTimes = 0
    /// 灯状态
    @Published var lights = [[Light]]()
    @Published var isWin = false
    /// 当前游戏状态
    private var currentStatus: WatchGameStatus = .during {
        didSet {
            switch currentStatus {
            case .win: isWin = true
            case .lose: isWin = false
            case .during: break
            }
        }
    }
    
    /// 游戏尺寸大小
    private(set) var size: Int?
    /// 游戏计时器
    private var timer: Timer?
    /// 游戏持续时间
    private var durations = 1
    private var row = 0
    private var column = 0
    private var pRow = 0
    private var pColumn = 0
    
    /// 游戏控制器暂停
    private var isPause = false
    
    // MARK: - Init
    
    /// 便捷构造方法
    /// - Parameters:
    ///   - size: 游戏布局尺寸,默认值 5x5
    ///   - lightSequence: 亮灯序列,默认全灭
    convenience init(size: Int = 5,
                     lightSequence: [Int] = [Int]()) {
        
        self.init()
        
        var size = size
        // 太大了不好玩
        if size > 8 {
            size = 7
        }
        // 太小了没意思
        if size < 2 {
            size = 2
        }
        self.size = size
        lights = Array(repeating: Array(repeating: Light(), count: size), count: size)
        
//        initGameController()
        start(lightSequence)
    }
    
    // MARK: Public
    
    /// 游戏配置
    /// - Parameter lightSequence: 亮灯序列
    func start(_ lightSequence: [Int]) {
        currentStatus = .during
        clickTimes = 0
        updateLightStatus(lightSequence)
        
        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { timer in
            let min = self.durations >= 60 ? self.durations / 60 : 0
            let seconds = self.durations - min * 60
            
            
            let minString = min >= 10 ? "\(min)" : "0\(min)"
            let secondString = self.durations - min * 60 >= 10 ? "\(seconds)" : "0\(seconds)"
            self.timeString = minString + ":" + secondString
            
            self.durations += 1
        })
    }
    
    /// 停止
    func timerStop() {
        timer?.fireDate = Date.distantFuture
    }
    
    /// 重新创建
    func timerRestart() {
        isPause = false
        durations = 0
        timeString = "00:00"
        timer?.fireDate = Date()
    }
    
    /// 获取灯的尺寸
    func circleWidth() -> CGFloat {
        guard let size = size else { return 0 }
        
        /// 距离屏幕左右两边的间距
        let padding: CGFloat = 20
        /// 左右两灯之间的间距
        let innerSpacing: CGFloat = 20
        
        let screenBounds = WKInterfaceDevice.current().screenBounds
        var circleWidth = (screenBounds.width - padding - (CGFloat(size) * innerSpacing)) / CGFloat(size)
        
        // 太大了会很丑,过滤下
        if circleWidth > screenBounds.width / 5 {
            circleWidth = screenBounds.width / 5
        }
    
        return circleWidth
    }
    
    /// 通过坐标索引修改灯状态
    /// - Parameters:
    ///   - column: 灯-列索引
    ///   - size: 灯-行索引
    func updateLightStatus(column: Int, row: Int, userTouch: Bool) {
        lights[row][column].status.toggle()
        self.column = row
        self.row = column
        
        // 上
        let top = row - 1
        if !(top < 0) {
            lights[top][column].status.toggle()
        }
        // 下
        let bottom = row + 1
        if !(bottom > lights.count - 1) {
            lights[bottom][column].status.toggle()
        }
        // 左
        let left = column - 1
        if !(left < 0) {
            lights[row][left].status.toggle()
        }
        // 右
        let right = column + 1
        if !(right > lights.count - 1) {
            lights[row][right].status.toggle()
        }
        
        updateGameStatus()
        
//        if (userTouch) {
//            disSelectedGameControllerStatus()
//        }
    }
    
    // MARK: Private
    
    /// 通过亮灯序列修改灯状态
    /// - Parameter lightSequence: 亮灯序列
    private func updateLightStatus(_ lightSequence: [Int]) {
        guard let size = size else { return }
        for lightIndex in lightSequence {
            var index = lightIndex
            // 防止数组越出最大边界处
            if index >= size * size {
                index = size * size - 1
            }
            let row = lightIndex / size
            let column = lightIndex % size
            // column 不为 0,说明非最后一个
            // row 为 0,说明为第一行
            updateLightStatus(column: column, row: row, userTouch: true)
        }
    }
    
    private func updateLightSelected() {
        lights[pColumn][pRow].selected = false
        lights[column][row].selected = true
        
        pRow = row
        pColumn = column
    }
    
//    private func disSelectedGameControllerStatus() {
//        lights[pColumn][pRow].selected = false
//    }
Download .txt
gitextract_jbiqqmeb/

├── LICENSE
├── README.md
├── bounceGame/
│   ├── bounceGame/
│   │   ├── Actions.sks
│   │   ├── AppDelegate.swift
│   │   ├── Assets.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   └── Contents.json
│   │   ├── Ball/
│   │   │   ├── Ball.swift
│   │   │   ├── Box.swift
│   │   │   └── Label.swift
│   │   ├── Base.lproj/
│   │   │   ├── LaunchScreen.storyboard
│   │   │   └── Main.storyboard
│   │   ├── Define.swift
│   │   ├── Extension.swift
│   │   ├── GameScene.sks
│   │   ├── GameScene.swift
│   │   ├── GameViewController.swift
│   │   └── Info.plist
│   └── bounceGame.xcodeproj/
│       ├── project.pbxproj
│       ├── project.xcworkspace/
│       │   ├── contents.xcworkspacedata
│       │   ├── xcshareddata/
│       │   │   └── IDEWorkspaceChecks.plist
│       │   └── xcuserdata/
│       │       └── pjhubs.xcuserdatad/
│       │           └── UserInterfaceState.xcuserstate
│       └── xcuserdata/
│           └── pjhubs.xcuserdatad/
│               ├── xcdebugger/
│               │   └── Breakpoints_v2.xcbkptlist
│               └── xcschemes/
│                   └── xcschememanagement.plist
├── liGame/
│   ├── liGame/
│   │   ├── AppDelegate.swift
│   │   ├── Assets.xcassets/
│   │   │   ├── 01.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── AppIcon-1.appiconset/
│   │   │   │   └── Contents.json
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   ├── Contents.json
│   │   │   ├── Line0.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Line1.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Line2.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── Line3.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_1.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_10.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_11.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_12.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_13.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_14.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_15.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_16.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_17.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_18.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_2.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_3.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_4.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_5.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_6.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_7.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_8.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── created_9.imageset/
│   │   │   │   └── Contents.json
│   │   │   ├── finalMan.imageset/
│   │   │   │   └── Contents.json
│   │   │   └── finalManContent.imageset/
│   │   │       └── Contents.json
│   │   ├── Base.lproj/
│   │   │   ├── LaunchScreen.storyboard
│   │   │   └── Main.storyboard
│   │   ├── Extension/
│   │   │   ├── Animation.swift
│   │   │   ├── Define.swift
│   │   │   ├── UIColor+Extension.swift
│   │   │   ├── UIImage+Extension.swift
│   │   │   └── UIView+Extension.swift
│   │   ├── Info.plist
│   │   ├── View/
│   │   │   ├── Bottom/
│   │   │   │   ├── LiBottomCollectionView.swift
│   │   │   │   ├── LiBottomCollectionViewCell.swift
│   │   │   │   └── LiBottomView.swift
│   │   │   └── Puzzle.swift
│   │   └── ViewController.swift
│   └── liGame.xcodeproj/
│       ├── project.pbxproj
│       ├── project.xcworkspace/
│       │   ├── contents.xcworkspacedata
│       │   ├── xcshareddata/
│       │   │   └── IDEWorkspaceChecks.plist
│       │   └── xcuserdata/
│       │       ├── pjhubs.xcuserdatad/
│       │       │   └── UserInterfaceState.xcuserstate
│       │       └── wengpeijun.xcuserdatad/
│       │           └── UserInterfaceState.xcuserstate
│       └── xcuserdata/
│           ├── pjhubs.xcuserdatad/
│           │   ├── xcdebugger/
│           │   │   └── Breakpoints_v2.xcbkptlist
│           │   └── xcschemes/
│           │       └── xcschememanagement.plist
│           └── wengpeijun.xcuserdatad/
│               ├── xcdebugger/
│               │   └── Breakpoints_v2.xcbkptlist
│               └── xcschemes/
│                   └── xcschememanagement.plist
└── lightGame/
    ├── light-game/
    │   ├── AppDelegate.swift
    │   ├── Assets.xcassets/
    │   │   ├── AppIcon.appiconset/
    │   │   │   └── Contents.json
    │   │   └── Contents.json
    │   ├── Base.lproj/
    │   │   └── LaunchScreen.storyboard
    │   ├── ContentView.swift
    │   ├── Info.plist
    │   ├── Model/
    │   │   ├── GameController.swift
    │   │   ├── GameManager.swift
    │   │   └── Light.swift
    │   ├── Preview Content/
    │   │   └── Preview Assets.xcassets/
    │   │       └── Contents.json
    │   └── SceneDelegate.swift
    ├── light-game.xcodeproj/
    │   ├── project.pbxproj
    │   ├── project.xcworkspace/
    │   │   ├── contents.xcworkspacedata
    │   │   ├── xcshareddata/
    │   │   │   └── IDEWorkspaceChecks.plist
    │   │   └── xcuserdata/
    │   │       ├── pjhubs.xcuserdatad/
    │   │       │   └── UserInterfaceState.xcuserstate
    │   │       └── wengpeijun.xcuserdatad/
    │   │           └── UserInterfaceState.xcuserstate
    │   └── xcuserdata/
    │       ├── pjhubs.xcuserdatad/
    │       │   ├── xcdebugger/
    │       │   │   └── Breakpoints_v2.xcbkptlist
    │       │   └── xcschemes/
    │       │       └── xcschememanagement.plist
    │       └── wengpeijun.xcuserdatad/
    │           ├── xcdebugger/
    │           │   └── Breakpoints_v2.xcbkptlist
    │           └── xcschemes/
    │               └── xcschememanagement.plist
    ├── watchapp/
    │   ├── Assets.xcassets/
    │   │   ├── AppIcon.appiconset/
    │   │   │   └── Contents.json
    │   │   └── Contents.json
    │   ├── Base.lproj/
    │   │   └── Interface.storyboard
    │   └── Info.plist
    └── watchapp Extension/
        ├── Assets.xcassets/
        │   ├── Complication.complicationset/
        │   │   ├── Circular.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Contents.json
        │   │   ├── Extra Large.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Graphic Bezel.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Graphic Circular.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Graphic Corner.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Graphic Large Rectangular.imageset/
        │   │   │   └── Contents.json
        │   │   ├── Modular.imageset/
        │   │   │   └── Contents.json
        │   │   └── Utilitarian.imageset/
        │   │       └── Contents.json
        │   └── Contents.json
        ├── ExtensionDelegate.swift
        ├── HostingController.swift
        ├── Info.plist
        ├── Preview Content/
        │   └── Preview Assets.xcassets/
        │       └── Contents.json
        ├── WatchContentView.swift
        └── WatchGameManager.swift
Condensed preview — 114 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (210K chars).
[
  {
    "path": "LICENSE",
    "chars": 1063,
    "preview": "MIT License\n\nCopyright (c) 2019 PJHubs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
  },
  {
    "path": "README.md",
    "chars": 1386,
    "preview": "# 《Swift 游戏开发》\n\n这里汇集了我的小专栏《Swift 游戏开发》的全部代码,小专栏地址:https://xiaozhuanlan.com/pjhubs-swift-game\n\n![](https://images.xiaozhu"
  },
  {
    "path": "bounceGame/bounceGame/AppDelegate.swift",
    "chars": 1817,
    "preview": "//\n//  AppDelegate.swift\n//  bounceGame\n//\n//  Created by 翁培钧 on 2019/12/22.\n//  Copyright © 2019 翁培钧. All rights reserv"
  },
  {
    "path": "bounceGame/bounceGame/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1590,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "bounceGame/bounceGame/Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "bounceGame/bounceGame/Ball/Ball.swift",
    "chars": 872,
    "preview": "//\n//  Ball.swift\n//  bounceGame\n//\n//  Created by 翁培钧 on 2019/12/29.\n//  Copyright © 2019 翁培钧. All rights reserved.\n//\n"
  },
  {
    "path": "bounceGame/bounceGame/Ball/Box.swift",
    "chars": 164,
    "preview": "//\n//  Box.swift\n//  bounceGame\n//\n//  Created by 翁培钧 on 2020/1/7.\n//  Copyright © 2020 翁培钧. All rights reserved.\n//\n\nim"
  },
  {
    "path": "bounceGame/bounceGame/Ball/Label.swift",
    "chars": 187,
    "preview": "//\n//  Label.swift\n//  bounceGame\n//\n//  Created by 翁培钧 on 2020/1/8.\n//  Copyright © 2020 翁培钧. All rights reserved.\n//\n\n"
  },
  {
    "path": "bounceGame/bounceGame/Base.lproj/LaunchScreen.storyboard",
    "chars": 1665,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "bounceGame/bounceGame/Base.lproj/Main.storyboard",
    "chars": 1661,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "bounceGame/bounceGame/Define.swift",
    "chars": 315,
    "preview": "//\n//  Define.swift\n//  bounceGame\n//\n//  Created by 翁培钧 on 2019/12/30.\n//  Copyright © 2019 翁培钧. All rights reserved.\n/"
  },
  {
    "path": "bounceGame/bounceGame/Extension.swift",
    "chars": 143,
    "preview": "//\n//  Extension.swift\n//  bounceGame\n//\n//  Created by 翁培钧 on 2020/1/8.\n//  Copyright © 2020 翁培钧. All rights reserved.\n"
  },
  {
    "path": "bounceGame/bounceGame/GameScene.swift",
    "chars": 6868,
    "preview": "//\n//  GameScene.swift\n//  bounceGame\n//\n//  Created by 翁培钧 on 2019/12/22.\n//  Copyright © 2019 翁培钧. All rights reserved"
  },
  {
    "path": "bounceGame/bounceGame/GameViewController.swift",
    "chars": 724,
    "preview": "//\n//  GameViewController.swift\n//  bounceGame\n//\n//  Created by 翁培钧 on 2019/12/22.\n//  Copyright © 2019 翁培钧. All rights"
  },
  {
    "path": "bounceGame/bounceGame/Info.plist",
    "chars": 1417,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "bounceGame/bounceGame.xcodeproj/project.pbxproj",
    "chars": 15817,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 50;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "bounceGame/bounceGame.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 155,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:bounceGame.xcod"
  },
  {
    "path": "bounceGame/bounceGame.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "bounceGame/bounceGame.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
    "chars": 840,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n   uuid = \"F52A3FF6-A55D-463E-895F-7E3D1A48B3E6\"\n   type = \"1\"\n   version"
  },
  {
    "path": "bounceGame/bounceGame.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 345,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "liGame/liGame/AppDelegate.swift",
    "chars": 2155,
    "preview": "//\n//  AppDelegate.swift\n//  liGame\n//\n//  Created by 翁培钧 on 2019/9/4.\n//  Copyright © 2019 翁培钧. All rights reserved.\n//"
  },
  {
    "path": "liGame/liGame/Assets.xcassets/01.imageset/Contents.json",
    "chars": 299,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/AppIcon-1.appiconset/Contents.json",
    "chars": 1590,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "liGame/liGame/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1590,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "liGame/liGame/Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "liGame/liGame/Assets.xcassets/Line0.imageset/Contents.json",
    "chars": 305,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/Line1.imageset/Contents.json",
    "chars": 305,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/Line2.imageset/Contents.json",
    "chars": 305,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/Line3.imageset/Contents.json",
    "chars": 305,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_1.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_1.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_10.imageset/Contents.json",
    "chars": 307,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_10.png\",\n      \"scale\" : \"1x\"\n    },\n   "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_11.imageset/Contents.json",
    "chars": 307,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_11.png\",\n      \"scale\" : \"1x\"\n    },\n   "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_12.imageset/Contents.json",
    "chars": 307,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_12.png\",\n      \"scale\" : \"1x\"\n    },\n   "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_13.imageset/Contents.json",
    "chars": 307,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_13.png\",\n      \"scale\" : \"1x\"\n    },\n   "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_14.imageset/Contents.json",
    "chars": 307,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_14.png\",\n      \"scale\" : \"1x\"\n    },\n   "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_15.imageset/Contents.json",
    "chars": 307,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_15.png\",\n      \"scale\" : \"1x\"\n    },\n   "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_16.imageset/Contents.json",
    "chars": 307,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_16.png\",\n      \"scale\" : \"1x\"\n    },\n   "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_17.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_1.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_18.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_3.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_2.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_2.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_3.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_3.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_4.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_4.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_5.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_5.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_6.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_6.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_7.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_7.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_8.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_8.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/created_9.imageset/Contents.json",
    "chars": 306,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"created_9.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/finalMan.imageset/Contents.json",
    "chars": 305,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "liGame/liGame/Assets.xcassets/finalManContent.imageset/Contents.json",
    "chars": 312,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "liGame/liGame/Base.lproj/LaunchScreen.storyboard",
    "chars": 1658,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "liGame/liGame/Base.lproj/Main.storyboard",
    "chars": 1597,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "liGame/liGame/Extension/Animation.swift",
    "chars": 1327,
    "preview": "//\n//  Animation.swift\n//  WWDC19\n//\n//  Created by PJHubs on 2019/3/20.\n//  Copyright © 2019 PJHubs. All rights reserve"
  },
  {
    "path": "liGame/liGame/Extension/Define.swift",
    "chars": 594,
    "preview": "//\n//  Define.swift\n//  liGame\n//\n//  Created by 翁培钧 on 2019/9/4.\n//  Copyright © 2019 翁培钧. All rights reserved.\n//\n\nimp"
  },
  {
    "path": "liGame/liGame/Extension/UIColor+Extension.swift",
    "chars": 588,
    "preview": "//\n//  UIColor+Extension.swift\n//  liGame\n//\n//  Created by 翁培钧 on 2019/9/4.\n//  Copyright © 2019 翁培钧. All rights reserv"
  },
  {
    "path": "liGame/liGame/Extension/UIImage+Extension.swift",
    "chars": 739,
    "preview": "//\n//  UIImage+Extension.swift\n//  liGame\n//\n//  Created by 翁培钧 on 2019/9/6.\n//  Copyright © 2019 翁培钧. All rights reserv"
  },
  {
    "path": "liGame/liGame/Extension/UIView+Extension.swift",
    "chars": 3255,
    "preview": "//\n//  UIView+Extension.swift\n//  liGame\n//\n//  Created by 翁培钧 on 2019/9/4.\n//  Copyright © 2019 翁培钧. All rights reserve"
  },
  {
    "path": "liGame/liGame/Info.plist",
    "chars": 1463,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "liGame/liGame/View/Bottom/LiBottomCollectionView.swift",
    "chars": 2169,
    "preview": "//\n//  LiBottomCollectionView.swift\n//  liGame\n//\n//  Created by pjhubs on 2019/9/8.\n//  Copyright © 2019 翁培钧. All right"
  },
  {
    "path": "liGame/liGame/View/Bottom/LiBottomCollectionViewCell.swift",
    "chars": 2704,
    "preview": "//\n//  LiBottomCollectionViewCell.swift\n//  liGame\n//\n//  Created by pjhubs on 2019/9/8.\n//  Copyright © 2019 翁培钧. All r"
  },
  {
    "path": "liGame/liGame/View/Bottom/LiBottomView.swift",
    "chars": 4009,
    "preview": "//\n//  LiBottomView.swift\n//  liGame\n//\n//  Created by pjhubs on 2019/9/8.\n//  Copyright © 2019 翁培钧. All rights reserved"
  },
  {
    "path": "liGame/liGame/View/Puzzle.swift",
    "chars": 3282,
    "preview": "//\n//  Puzzle.swift\n//  liGame\n//\n//  Created by 翁培钧 on 2019/9/6.\n//  Copyright © 2019 翁培钧. All rights reserved.\n//\n\nimp"
  },
  {
    "path": "liGame/liGame/ViewController.swift",
    "chars": 10744,
    "preview": "//\n//  ViewController.swift\n//  liGame\n//\n//  Created by 翁培钧 on 2019/9/4.\n//  Copyright © 2019 翁培钧. All rights reserved."
  },
  {
    "path": "liGame/liGame.xcodeproj/project.pbxproj",
    "chars": 17072,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 50;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "liGame/liGame.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 151,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:liGame.xcodepro"
  },
  {
    "path": "liGame/liGame.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "liGame/liGame.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
    "chars": 1489,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n   uuid = \"C53C8EF3-EAAB-4A91-9ADC-B60CB1951A02\"\n   type = \"1\"\n   version"
  },
  {
    "path": "liGame/liGame.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 341,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "liGame/liGame.xcodeproj/xcuserdata/wengpeijun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
    "chars": 2839,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n   uuid = \"A059B4AD-2C70-4238-AA7A-BE509499A88D\"\n   type = \"1\"\n   version"
  },
  {
    "path": "liGame/liGame.xcodeproj/xcuserdata/wengpeijun.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 341,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "lightGame/light-game/AppDelegate.swift",
    "chars": 1408,
    "preview": "//\n//  AppDelegate.swift\n//  light-game\n//\n//  Created by pjhubs on 2019/8/29.\n//  Copyright © 2019 PJHubs. All rights r"
  },
  {
    "path": "lightGame/light-game/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1590,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "lightGame/light-game/Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "lightGame/light-game/Base.lproj/LaunchScreen.storyboard",
    "chars": 1665,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "lightGame/light-game/ContentView.swift",
    "chars": 2325,
    "preview": "//\n//  ContentView.swift\n//  light-game\n//\n//  Created by pjhubs on 2019/8/29.\n//  Copyright © 2019 PJHubs. All rights r"
  },
  {
    "path": "lightGame/light-game/Info.plist",
    "chars": 1884,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "lightGame/light-game/Model/GameController.swift",
    "chars": 3661,
    "preview": "//\n//  GameController.swift\n//  light-game\n//\n//  Created by 翁培钧 on 2019/11/30.\n//  Copyright © 2019 PJHubs. All rights "
  },
  {
    "path": "lightGame/light-game/Model/GameManager.swift",
    "chars": 6866,
    "preview": "//\n//  GameManager.swift\n//  light-game\n//\n//  Created by pjhubs on 2019/8/30.\n//  Copyright © 2019 PJHubs. All rights r"
  },
  {
    "path": "lightGame/light-game/Model/Light.swift",
    "chars": 242,
    "preview": "//\n//  Light.swift\n//  light-game\n//\n//  Created by pjhubs on 2019/8/29.\n//  Copyright © 2019 PJHubs. All rights reserve"
  },
  {
    "path": "lightGame/light-game/Preview Content/Preview Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "lightGame/light-game/SceneDelegate.swift",
    "chars": 2858,
    "preview": "//\n//  SceneDelegate.swift\n//  light-game\n//\n//  Created by pjhubs on 2019/8/29.\n//  Copyright © 2019 PJHubs. All rights"
  },
  {
    "path": "lightGame/light-game.xcodeproj/project.pbxproj",
    "chars": 28357,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 50;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "lightGame/light-game.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 155,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:light-game.xcod"
  },
  {
    "path": "lightGame/light-game.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "lightGame/light-game.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
    "chars": 2926,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n   uuid = \"1E1C8DCA-4FD3-4651-B05E-8AE053F638C6\"\n   type = \"1\"\n   version"
  },
  {
    "path": "lightGame/light-game.xcodeproj/xcuserdata/pjhubs.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 455,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "lightGame/light-game.xcodeproj/xcuserdata/wengpeijun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
    "chars": 140,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n   uuid = \"9170105D-1022-4B15-93E6-44F08E915BF2\"\n   type = \"1\"\n   version"
  },
  {
    "path": "lightGame/light-game.xcodeproj/xcuserdata/wengpeijun.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 345,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "lightGame/watchapp/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1542,
    "preview": "{\n  \"images\" : [\n    {\n      \"size\" : \"24x24\",\n      \"idiom\" : \"watch\",\n      \"scale\" : \"2x\",\n      \"role\" : \"notificati"
  },
  {
    "path": "lightGame/watchapp/Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "lightGame/watchapp/Base.lproj/Interface.storyboard",
    "chars": 910,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder.WatchKit.Storyboard\" version=\"3.0\" too"
  },
  {
    "path": "lightGame/watchapp/Info.plist",
    "chars": 1080,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json",
    "chars": 442,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"watch\",\n      \"scale\" : \"2x\",\n      \"screen-width\" : \"<=145\"\n    },\n    {\n      "
  },
  {
    "path": "lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Contents.json",
    "chars": 995,
    "preview": "{\n  \"assets\" : [\n    {\n      \"idiom\" : \"watch\",\n      \"filename\" : \"Circular.imageset\",\n      \"role\" : \"circular\"\n    },"
  },
  {
    "path": "lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json",
    "chars": 442,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"watch\",\n      \"scale\" : \"2x\",\n      \"screen-width\" : \"<=145\"\n    },\n    {\n      "
  },
  {
    "path": "lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json",
    "chars": 442,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"watch\",\n      \"scale\" : \"2x\",\n      \"screen-width\" : \"<=145\"\n    },\n    {\n      "
  },
  {
    "path": "lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json",
    "chars": 442,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"watch\",\n      \"scale\" : \"2x\",\n      \"screen-width\" : \"<=145\"\n    },\n    {\n      "
  },
  {
    "path": "lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json",
    "chars": 442,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"watch\",\n      \"scale\" : \"2x\",\n      \"screen-width\" : \"<=145\"\n    },\n    {\n      "
  },
  {
    "path": "lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json",
    "chars": 442,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"watch\",\n      \"scale\" : \"2x\",\n      \"screen-width\" : \"<=145\"\n    },\n    {\n      "
  },
  {
    "path": "lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json",
    "chars": 442,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"watch\",\n      \"scale\" : \"2x\",\n      \"screen-width\" : \"<=145\"\n    },\n    {\n      "
  },
  {
    "path": "lightGame/watchapp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json",
    "chars": 442,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"watch\",\n      \"scale\" : \"2x\",\n      \"screen-width\" : \"<=145\"\n    },\n    {\n      "
  },
  {
    "path": "lightGame/watchapp Extension/Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "lightGame/watchapp Extension/ExtensionDelegate.swift",
    "chars": 2959,
    "preview": "//\n//  ExtensionDelegate.swift\n//  watchapp Extension\n//\n//  Created by 翁培钧 on 2019/12/7.\n//  Copyright © 2019 PJHubs. A"
  },
  {
    "path": "lightGame/watchapp Extension/HostingController.swift",
    "chars": 328,
    "preview": "//\n//  HostingController.swift\n//  watchapp Extension\n//\n//  Created by 翁培钧 on 2019/12/7.\n//  Copyright © 2019 PJHubs. A"
  },
  {
    "path": "lightGame/watchapp Extension/Info.plist",
    "chars": 1214,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "lightGame/watchapp Extension/Preview Content/Preview Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "lightGame/watchapp Extension/WatchContentView.swift",
    "chars": 2030,
    "preview": "//\n//  WatchContentView.swift\n//  watchapp Extension\n//\n//  Created by 翁培钧 on 2019/12/7.\n//  Copyright © 2019 PJHubs. Al"
  },
  {
    "path": "lightGame/watchapp Extension/WatchGameManager.swift",
    "chars": 6917,
    "preview": "//\n//  WatchGameManager.swift\n//  watchapp Extension\n//\n//  Created by 翁培钧 on 2019/12/7.\n//  Copyright © 2019 PJHubs. Al"
  }
]

// ... and 7 more files (download for full content)

About this extraction

This page contains the full source code of the windstormeye/SwiftGame GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 114 files (179.6 KB), approximately 58.1k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!