๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŽ iOS/UI

[๐Ÿงฉ Creative Coding] ์ค„์— ๋งค๋‹ฌ๋ ค ํ”๋“ค๋ฆฌ๋Š” ์ƒ์ž ๋งŒ๋“ค๊ธฐ (feat. Interactive Developer)

by Fomagran ๐Ÿ’ป 2021. 11. 23.
728x90
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š” Foma ๐Ÿ’ป ์ž…๋‹ˆ๋‹ค!

 

์˜ค๋Š˜์€ ์ค„์— ๋งค๋‹ฌ๋ ค ํ”๋“ค๋ฆฌ๋Š” ์ƒ์ž๋ฅผ ๋งŒ๋“ค์–ด ๋ณผ๊ฑด๋ฐ์š”.

 

์ด๊ฑด ์ œ๊ฐ€ ์กด๊ฒฝํ•˜๋Š” ๊ฐœ๋ฐœ์ž์ด๊ธฐ๋„ ํ•œ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ๋””๋ฒจ๋กœํผ ๊น€์ข…๋ฏผ๋‹˜์˜ ์œ ํŠœ๋ธŒ ์ฑ„๋„์— ์˜ฌ๋ผ์˜จ ํŠœํ† ๋ฆฌ์–ผ ์ค‘ ํ•˜๋‚˜์ธ๋ฐ์š”.

 

์˜ˆ์ „๋ถ€ํ„ฐ ์ด๋Ÿฐ ์ฐฝ์˜์ ์ธ ์ฝ”๋”ฉ, ์˜ˆ์ˆ ์ ์ธ ์ฝ”๋”ฉ์„ ํ•˜๊ณ ์‹ถ์€ ์š•์‹ฌ์ด ๋งŽ์•˜์—ˆ๋Š”๋ฐ ์ด๋ฒˆ ๊ธฐํšŒ์— ๊น€์ข…๋ฏผ๋‹˜์„ ๋”ฐ๋ผ์„œ ๊ตฌํ˜„ํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

 

์œ„ ์˜์ƒ์„ ๋ณด๋ฉฐ ๋‚˜๋ฆ„ ์ œ ๋ฐฉ์‹๋Œ€๋กœ Swift๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

 

๋ฐ”๋กœ ์‹œ์ž‘ํ• ๊ฒŒ์š”~


View

 

๋จผ์ € ์ƒ์ž์™€ ๋นจ๊ฐ„ ์ ์„ UIView๋กœ ์„ธํŒ…ํ•ด์ค๋‹ˆ๋‹ค.

 

(์ €๋Š” ์ƒ์ž ๊ฐ€์šด๋ฐ์— ์ œ ์ด๋ฆ„์„ ๋„ฃ์–ด์„œ ๋ณด์—ฌ์ค„ ๊ฑฐ๊ธฐ ๋•Œ๋ฌธ์— label๋„ ๋„ฃ์—ˆ์Šต๋‹ˆ๋‹ค.)

 

 let square:UIView = {
        let view:UIView = UIView()
        view.backgroundColor = .systemCyan
        return view
    }()
    
    let redDot1:UIView = {
        let view:UIView = UIView()
        view.backgroundColor = .clear
        return view
    }()
    
    let redDot2:UIView = {
        let view:UIView = UIView()
        view.backgroundColor = .clear
        return view
    }()
    
    let label:UILabel = {
        let label:UILabel = UILabel()
        label.text = "Fomagran"
        label.font = .systemFont(ofSize: 18, weight: .bold)
        label.textColor = .white
        return label
    }()

1. ์ƒ์ž ์›€์ง์ด๊ธฐ

 

์ƒ์ž๋ฅผ ํ„ฐ์น˜ํ•ด์„œ ์›€์ง์ด๊ฒŒ ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ์š”?

 

๋ฐ”๋กœ ํŒฌ์ œ์Šค์ณ๋ผ๋Š” ๊ฒƒ์„ ์ด์šฉํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ƒ์ž์— ์•„๋ž˜์™€ ๊ฐ™์ด ํŒฌ์ œ์Šค์ณ๋ฅผ ๋‹ฌ์•„์ค๋‹ˆ๋‹ค.

 

private func setPanGesture() {
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.dragSquare(_:)))
        square.addGestureRecognizer(panGesture)
    }

 

์ƒ์ž๋ฅผ ๋“œ๋ž˜๊ทธ ํ–ˆ์„ ๋•Œ ์•„๋ž˜์™€ ๊ฐ™์ด ์‹คํ–‰์‹œ์ผœ์ฃผ๋ฉด 

 

    @objc func dragSquare(_ sender: UIPanGestureRecognizer) {
        let transition = sender.translation(in: square)
        let newX = square.center.x + transition.x
        let newY = square.center.y + transition.y
        square.center = CGPoint(x: newX, y: newY)
        sender.setTranslation(CGPoint.zero, in: square)
    }

 

์ƒ์ž๋ฅผ ์›€์ง์ผ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 


2. ์ƒ์ž๋ฅผ ํ„ฐ์น˜ํ•œ ๋ถ€๋ถ„ ๋นจ๊ฐ„ ์ ์œผ๋กœ ํ‘œ์‹œํ•˜๊ธฐ

 

์œ„ ์˜์ƒ์„ ๋ณด๋ฉด ์ƒ์ž๋ฅผ ํ„ฐ์น˜ํ•œ ๋ถ€๋ถ„์— ๋นจ๊ฐ„ ์ ์ด ์ƒ๊ธฐ๊ณ  ์„ ์ด ์ƒ๊ฒจ์„œ ๋งค๋‹ฌ๋ ค ์›€์ง์ด์ฃ ?

 

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ์ƒ์ž๋ฅผ ๊ฐ€์žฅ ์ฒ˜์Œ์— ํ„ฐ์น˜ํ•œ ๋ถ€๋ถ„์„ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ์„๊นŒ์š”?

 

๋ฐ”๋กœ ์ฒ˜์Œ ๋“œ๋ž˜๊ทธ๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ ์œ„์น˜๋ฅผ ์•Œ์•„๋‚ด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

UIPanGestureRecognizer๋ฅผ ์ด์šฉํ•ด์„œ ๋“œ๋ž˜๊ทธ๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ์œ„์น˜๋ฅผ ์•Œ์•„๋ƒ…๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณค ๋นจ๊ฐ„์ 1์˜ ์ƒ‰์„ ๋นจ๊ฐ„์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”์ค๋‹ˆ๋‹ค.

 

 @objc func dragSquare(_ sender: UIPanGestureRecognizer) {
        if sender.state == .began {
            let location = sender.location(in: view) //๋“œ๋ž˜๊ทธ๋ฅผ ์‹œ์ž‘ํ•œ ์œ„์น˜
            redDot1.center = location
            redDot1.backgroundColor = .red
            ...

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋“œ๋ž˜๊ทธ๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ ์ง€์ ์ด ๋นจ๊ฐ„์ƒ‰์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

 

 


2. ๋‘ ๋ฒˆ์งธ ๋นจ๊ฐ„์  ๋“œ๋ž˜๊ทธ ์œ„์น˜์— ํ‘œ์‹œํ•˜๊ธฐ

 

์ƒ์ž๋ฅผ ํ„ฐ์น˜ํ•œ ๋ถ€๋ถ„์— ๋นจ๊ฐ„ ์ ์„ ํ‘œ์‹œํ–ˆ๋‹ค๋ฉด ๋“œ๋ž˜๊ทธ๋ฅผ ํ•˜๋Š” ์œ„์น˜์— ๋”ฐ๋ผ ํ‘œ์‹œ๋˜๋Š” ๋นจ๊ฐ„ ์ ๋„ ๋ณด์—ฌ์ค˜์•ผ๊ฒ ์ฃ ?

 

๋“œ๋ž˜๊ทธ๊ฐ€ ๋ฐ”๋€” ๋•Œ์˜ ์œ„์น˜๋ฅผ ์•Œ์•„๋‚ด์–ด ๋นจ๊ฐ„์ 2์˜ ์œ„์น˜๋ฅผ ๋ฐ”๊ฟ”์ค๋‹ˆ๋‹ค.

 

 @objc func dragSquare(_ sender: UIPanGestureRecognizer) {
        if sender.state == .began {
            let location = sender.location(in: view) //๋“œ๋ž˜๊ทธ๋ฅผ ์‹œ์ž‘ํ•œ ์œ„์น˜
            redDot1.center = location
            redDot1.backgroundColor = .red
          }else if sender.state == .changed {
            redDot2.center = sender.location(in: view)
            redDot2.backgroundColor = .red
            ...

 

๊ทธ๋Ÿผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋“œ๋ž˜๊ทธ๋ฅผ ํ•˜๋ฉด ์ฒ˜์Œ ์œ„์น˜์™€ ๋“œ๋ž˜๊ทธ๋ฅผ ํ•˜๋Š” ์œ„์น˜์— ๋”ฐ๋ผ ๋นจ๊ฐ„์  ๋‘ ๊ฐœ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

 


3. ๋นจ๊ฐ„ ์  ๋‘ ๊ฐœ ์„ ์œผ๋กœ ์ž‡๊ธฐ

 

์ด์ œ ๋นจ๊ฐ„ ์  ๋‘ ๊ฐœ๋ฅผ ์„ ์œผ๋กœ ์ด์–ด์ค˜์•ผ๊ฒ ์ฃ ?

 

์„ ์„ ๋งŒ๋“ค์–ด ์ฃผ๊ธฐ ์œ„ํ•ด์„  CAShapeLayer๋กœ ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

private var line = CAShapeLayer()

 

์•„๋ž˜์™€ ๊ฐ™์ด ์‹œ์ž‘๊ณผ ๋์„ ์ง€์ •ํ•ด์ฃผ๊ณ  ์„ ์œผ๋กœ ์ด์–ด์ค๋‹ˆ๋‹ค.

 

 private func addLine(start: CGPoint,end:CGPoint) {
        line.removeFromSuperlayer()
        let linePath = UIBezierPath()
        linePath.move(to: start)
        linePath.addLine(to: end)
        line.path = linePath.cgPath
        line.strokeColor = UIColor.red.cgColor
        line.lineWidth = 1
        view.layer.addSublayer(line)
    }

 

๋นจ๊ฐ„์ 1๊ณผ ๋นจ๊ฐ„์ 2์˜ ์ค‘์•™ ๋ถ€๋ถ„์„ ์„ ์œผ๋กœ ์ด์–ด์ค๋‹ˆ๋‹ค.

 

 @objc func dragSquare(_ sender: UIPanGestureRecognizer) {
        if sender.state == .began {
            let location = sender.location(in: view) //๋“œ๋ž˜๊ทธ๋ฅผ ์‹œ์ž‘ํ•œ ์œ„์น˜
            redDot1.center = location
            redDot1.backgroundColor = .red
          }else if sender.state == .changed {
            redDot2.center = sender.location(in: view)
            redDot2.backgroundColor = .red
            addLine(start: redDot1.center,end:redDot2.center)
            ...

 

์•„๋ž˜์™€ ๊ฐ™์ด ์„ ์œผ๋กœ ๋‘ ๊ฐœ์˜ ์ ์ด ์ด์–ด์ง‘๋‹ˆ๋‹ค.

 


4. ๋“œ๋ž˜๊ทธ๊ฐ€ ๋๋‚˜๋ฉด ์„ ๊ณผ ์  ์‚ฌ๋ผ์ง€๊ฒŒ ํ•˜๊ธฐ

 

๋“œ๋ž˜๊ทธ๊ฐ€ ๋๋‚˜๋Š” ์ˆœ๊ฐ„์—๋Š” ์„ ๊ณผ ์ ์ด ์‚ฌ๋ผ์ ธ์•ผ๊ฒ ์ฃ ?

 

๋นจ๊ฐ„์  ๋‘ ๊ฐœ์™€ ์„ ์˜ ์ƒ‰์„ ๋ฐ”๊ฟ”์ฃผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์ค๋‹ˆ๋‹ค.

 

 private func changeColor(_ color:UIColor) {
        redDot1.backgroundColor = color
        redDot2.backgroundColor = color
        line.strokeColor = color.cgColor
    }

 

dragSquare ๋ฉ”์†Œ๋“œ์— ๋“œ๋ž˜๊ทธ๊ฐ€ ๋๋‚ฌ์„ ๋•Œ ์ƒ‰์„ ํˆฌ๋ช…์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”์ค๋‹ˆ๋‹ค.

 

 @objc func dragSquare(_ sender: UIPanGestureRecognizer) {
	...
    
    }else if sender.state == .ended {
            changeColor(.clear)
            ...

 

 


5. ํŠน์ • ๊ธธ์ด ์ด์ƒ ๋Š˜์–ด๋‚˜๋ฉด ๋นจ๊ฐ„์ 1 ์›€์ง์ด๊ธฐ

 

์„ ์„ ์žก์•„๋‹น๊ธฐ๋‹ค๊ฐ€ ํŠน์ • ๊ธธ์ด ์ด์ƒ ๋Š˜์–ด๋‚˜๋ฉด ๋นจ๊ฐ„์  1์„ ์›€์ง์ด๊ฒŒ ๋งŒ๋“ค์–ด ์ค„๊ฑด๋ฐ์š”.

 

๋จผ์ € ๋‘ ๊ฐœ์˜ ์ ์˜ ๊ธธ์ด๋ฅผ ์•Œ์•„๋‚ด์•ผ๊ฒ ์ฃ ?

์•„๋ž˜์™€ ๊ฐ™์ด ๋‘ ๊ฐœ์˜ ์ ์˜ ๊ธธ์ด๋ฅผ ์•Œ์•„๋ƒ…๋‹ˆ๋‹ค.

 

 private func getTwoPointDistance(_ point1:CGPoint,_ point2:CGPoint) -> CGFloat {
        let xDist:CGFloat = point2.x - point1.x
        let yDist:CGFloat = point2.y - point1.y
        return sqrt((xDist * xDist) + (yDist * yDist))
    }

 

dragSquare ๋ฉ”์„œ๋“œ์—์„œ ๋“œ๋ž˜๊ทธ๊ฐ€ ๋ณ€ํ•  ๋•Œ์— ์•„๋ž˜์™€ ๊ฐ™์ด ๋‘ ๊ฐœ์˜ ์ ์˜ ๊ธธ์ด๋ฅผ ์•Œ์•„๋‚ธ ๋’ค

 

ํŠน์ • ๊ธธ์ด ์ด์ƒ ๋Š˜์–ด๋‚˜๋ฉด ๋นจ๊ฐ„์ 2์˜ ์œ„์น˜๋กœ ๋นจ๊ฐ„์ 1์˜ ์œ„์น˜๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

        }else if sender.state == .changed {
            redDot2.center = sender.location(in: view)
            redDot2.backgroundColor = .red
            addLine(start: redDot1.center,end:redDot2.center)
            let distance:CGFloat = getTwoPointDistance(redDot1.center,redDot2.center)
            if distance > 100 {
                redDot1.center = redDot2.center
            }

 

์•„๋ž˜์™€ ๊ฐ™์ด ๋ณด๋ฉด ์ƒ์ž๊ฐ€ ์›€์ง์ด๋Š”๊ฒŒ ๋งค์šฐ ์–ด์ƒ‰ํ•˜์ฃ ?

 

UIView.animate๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์›€์ง์ž„์„ ํ›จ์”ฌ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

  if distance > 100 {
                UIView.animate(withDuration: 0.5) {
                    self.redDot1.center = self.redDot2.center
                }

 

 


6. ์„  ๋Š๊น€ ํ˜„์ƒ ํ•ด๊ฒฐํ•˜๊ธฐ

 

ํ•˜์ง€๋งŒ ์œ„์—์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ ์šฉํ–ˆ์„ ๋•Œ ๋ถ€๋“œ๋Ÿฌ์›Œ์ง€๊ธด ํ•˜์ง€๋งŒ ๋นจ๊ฐ„์ 1์ด ์ด๋™ ์ค‘์— ์ž ๊น ์„ ์ด ๋Š๊ธฐ๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ ์ด์œ ๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ ์šฉํ•˜๋ฉด ๋ฐ”๋€Œ๋Š” ๊ฐ’์— ๋”ฐ๋ผ ์„ ์ด ์—ฐ๊ฒฐ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋ฐ”๋€Œ๋Š” ๊ฐ’์— ๋”ฐ๋ผ ์„ ์„ ์—ฐ๊ฒฐํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ์š”?

 

๋ฐ”๋กœ CADisplayLink๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

CADisplayLink๋Š” ํ™”๋ฉด์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๋Š” NSObject์ธ๋ฐ์š”.

 

 

์•„๋ž˜์™€ ๊ฐ™์ด ์„ ์–ธํ•ด์ฃผ์‹œ๊ณ  

 

var displayLink:CADisplayLink?

 

๋””์Šคํ”Œ๋ ˆ์ด๋งํฌ๋ฅผ ์ƒ์„ฑํ•ด ์ฃผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์ค๋‹ˆ๋‹ค.

 

private func createDisplayLink() {
        let displaylink = CADisplayLink(target: self,selector: #selector(displayLinkLoop))
        displaylink.add(to: .current,forMode:.common)
        displayLink = displaylink
    }

 

๊ทธ๋ฆฌ๊ณ  ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์‹คํ–‰๋˜๊ธฐ ์ง์ „์— ๋””์Šคํ”Œ๋ ˆ์ด ๋งํฌ๋ฅผ ์ƒ์„ฑํ•ด ์ค๋‹ˆ๋‹ค.

 

          if distance > 100 {
                createDisplayLink()
                UIView.animate(withDuration: 0.5) {
                    self.redDot1.center = self.redDot2.center
                }

 

๊ทธ๋ฆฌ๊ณ  ๋””์Šคํ”Œ๋ ˆ์ด๋งํฌ๋ฅผ ์ถœ๋ ฅํ•ด๋ณด๋ฉด 

 

@objc func displayLinkLoop(displaylink: CADisplayLink) {
        print(displaylink)

 

ํ™”๋ฉด์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งˆ๋‹ค ์•„๋ž˜์™€ ๊ฐ™์ด ๋””์Šคํ”Œ๋ ˆ์ด ๋งํฌ๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

 

 

 

์ด๊ฒƒ์„ ์ด์šฉํ•ด์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋นจ๊ฐ„์ 1์„ ์ด๋™์‹œํ‚ค๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋นจ๊ฐ„์ 2์˜ ์œ„์น˜๋ฅผ ๊ธฐ์–ตํ•  goal์„ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

 

var goal = CGPoint()

 

์•„๋ž˜์™€ ๊ฐ™์ด ๋””์Šคํ”Œ๋ ˆ์ด๋งํฌ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์ง์ „์— goal์˜ ์œ„์น˜๋ฅผ ๋นจ๊ฐ„์ 2์˜ ์ค‘์•™์œผ๋กœ ์„ธํŒ…ํ•ฉ๋‹ˆ๋‹ค.

 

 if distance > 100 {
                goal = redDot2.center
                createDisplayLink()
            }

 

๊ทธ๋ฆฌ๊ณ  ๋””์Šคํ”Œ๋ ˆ์ด ๋งํฌ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฉ”์„œ๋“œ์— ์•„๋ž˜์™€ ๊ฐ™์ด goal์˜ ์œ„์น˜๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ์„ ์œผ๋กœ ์—ฐ๊ฒฐํ•ด์ค๋‹ˆ๋‹ค.

 

    @objc func displayLinkLoop(displaylink: CADisplayLink) {
        if round(redDot1.center.x) == round(goal.x) && round(redDot1.center.y) == round(goal.y){
            displaylink.invalidate()
            line.strokeColor = UIColor.clear.cgColor
            return
        }
        if round(redDot1.center.x) != round(goal.x) {
            redDot1.center.x += redDot1.center.x < goal.x ? 1: -1
        }

        if round(redDot1.center.y) != round(goal.y) {
            redDot1.center.y += redDot1.center.y < goal.y ? 1 : -1
        }
        
        addLine(start: redDot1.center,end: redDot2.center)
    }
}

 

๊ทธ๋Ÿผ ์•„๋ž˜์™€ ๊ฐ™์ด ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ด์šฉํ•˜์ง€ ์•Š๊ณ  ๋นจ๊ฐ„ ์ 1์˜ ์œ„์น˜๋ฅผ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


7. ๋นจ๊ฐ„์ 1์˜ ์œ„์น˜์— ๋”ฐ๋ผ ์ƒ์ž ์›€์ง์ด๊ธฐ

 

์ด์ œ ๋นจ๊ฐ„์ 1์˜ ์œ„์น˜์— ๋”ฐ๋ผ์„œ ์ƒ์ž๋ฅผ ์›€์ง์—ฌ๋ณด๋Š” ๊ฒƒ์„ ๊ตฌํ˜„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋นจ๊ฐ„์ 1์˜ ์œ„์น˜๋Š” ๋งจ ์ฒ˜์Œ ๋“œ๋ž˜๊ทธ๊ฐ€ ์‹œ์ž‘๋œ ๊ณณ์˜ ์œ„์น˜์ฃ ?

 

๊ณ ๋กœ ๋นจ๊ฐ„์ 1์˜ ์ค‘์•™๊ณผ ์ƒ์ž์˜ ์ค‘์•™์˜ ์ฐจ์ด๋ฅผ ๊ณ„์‚ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

๋นจ๊ฐ„์ 1๊ณผ ์ƒ์ž์˜ ์ฐจ์ด๋ฅผ ๊ธฐ๋กํ•  gap์„ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

 

private var gap:CGPoint = CGPoint()

 

๊ทธ๋ฆฌ๊ณ  ๋“œ๋ž˜๊ทธ๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ์ƒ์ž์™€ ๋นจ๊ฐ„ ์ ์˜ ์œ„์น˜๋ฅผ ๊ณ„์‚ฐํ•ด์„œ gap์— ์ €์žฅํ•ด์ค๋‹ˆ๋‹ค.

 

 if sender.state == .began {
            let location = sender.location(in: view)
            gap.x = square.center.x - location.x
            gap.y = square.center.y - location.y

 

๊ทธ ๋‹ค์Œ ๋””์Šคํ”Œ๋ ˆ์ด ๋งํฌ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ์ƒ์ž์˜ ์œ„์น˜๋ฅผ ์ฐจ์ด๋งŒํผ ๋”ํ•ด์ค€ ๊ฐ’์œผ๋กœ ์ง€์ •ํ•ด์ค๋‹ˆ๋‹ค.

 

    @objc func displayLinkLoop(displaylink: CADisplayLink) {
        if round(redDot1.center.x) == round(goal.x) && round(redDot1.center.y) == round(goal.y){
            displaylink.invalidate()
            line.strokeColor = UIColor.clear.cgColor
            return
        }
        if round(redDot1.center.x) != round(goal.x) {
            redDot1.center.x += redDot1.center.x < goal.x ? 1: -1
            square.center.x = redDot1.center.x + gap.x
        }

        if round(redDot1.center.y) != round(goal.y) {
            redDot1.center.y += redDot1.center.y < goal.y ? 1 : -1
            square.center.y = redDot1.center.y + gap.y
        }
        
        addLine(start: redDot1.center,end: redDot2.center)
    }

 

์•„๋ž˜์™€ ๊ฐ™์ด ๋นจ๊ฐ„์ 1์˜ ์œ„์น˜์— ๋”ฐ๋ผ ์ƒ์ž๊ฐ€ ์›€์ง์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 


8. ๋นจ๊ฐ„์ 1๊ณผ ๋นจ๊ฐ„์ 2์˜ ๊ฑฐ๋ฆฌ๋‘๊ธฐ(์˜ต์…”๋„)

 

๋นจ๊ฐ„์ 1์ด ๋นจ๊ฐ„์ 2์˜ ์œ„์น˜๋กœ ๊ฐ€๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๊ทธ ๊ทผ์ฒ˜๋กœ ๊ฐ€๊ฒŒ๋” ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ์—ˆ๋Š”๋ฐ์š”.

 

(์ด๊ฑด ํ•˜์…”๋„ ๋˜๊ณ  ์•ˆํ•˜์…”๋„ ๋ฉ๋‹ˆ๋‹ค.)

 

์ด๋ ‡๊ฒŒ ์„ค๋ช…ํ•˜๋ฉด ์ดํ•ด๊ฐ€ ์•ˆ๋˜๋‹ˆ ์™ผ์ชฝ์€ ๋นจ๊ฐ„์ 2์˜ ์ขŒํ‘œ๊นŒ์ง€ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ด๊ณ  ์˜ค๋ฅธ์ชฝ์€ ๋นจ๊ฐ„์ 2์˜ ๊ทผ์ฒ˜๊นŒ์ง€๋งŒ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

 

์ƒ์ž์˜ ์ค‘์•™์„ ๊ธฐ์ค€์œผ๋กœ x,y์˜ ์Œ์ˆ˜์™€ ์–‘์ˆ˜์— ๋”ฐ๋ผ ๋ฒ”์œ„๋ฅผ ๋‚˜๋ˆ„๊ณ  ๋นจ๊ฐ„์ 2์˜ ์œ„์น˜์— ๋”ฐ๋ผ ๋นจ๊ฐ„์ 1์˜ ์œ„์น˜๋ฅผ

 

๊ตฌํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

์•„๋ž˜์™€ ๊ฐ™์ด ๋ฒ”์œ„์— ๋”ฐ๋ผ ๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

  func getDestinationPoint(p2:CGPoint) -> CGPoint {
        if p2.x <= center.x  {
            //1
            if p2.y <= center.y {
                return CGPoint(x: p2.x+50, y: p2.y+50)
            //3
            }else {
                return CGPoint(x: p2.x+50, y: p2.y-50)
            }
        }else {
            //2
            if p2.y <= center.y {
                return CGPoint(x: p2.x-50, y: p2.y+50)
            //4
            }else {
                return CGPoint(x: p2.x-50, y: p2.y-50)
            }
        }
    }

 

goal์˜ ์œ„์น˜๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•ด์ค๋‹ˆ๋‹ค.

 

  if distance > 100 {
                goal = square.getDestinationPoint(p2: redDot2.center)
                createDisplayLink()
            }

9. ์ƒ์ž ํšŒ์ „ํ•˜๊ธฐ

 

์ค„์„ ๋‹น๊ฒจ ์ƒ์ž๋ฅผ ์›€์ง์ผ ๋•Œ ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ ์ƒ์ž๊ฐ€ ์•ฝ๊ฐ„์”ฉ ํšŒ์ „๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๊ฒƒ ๋˜ํ•œ ์œ„์ฒ˜๋Ÿผ ๋ฒ”์œ„๋ฅผ ๋‚˜๋ˆ  ๋นจ๊ฐ„์  2์˜ ์œ„์น˜์— ๋”ฐ๋ผ ์–ด๋Š ๋ฐฉํ–ฅ์ธ์ง€ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

๋ฒ”์œ„์— ๋”ฐ๋ผ ์•„๋ž˜์™€ ๊ฐ™์ด ํšŒ์ „๊ฐ’์„ ์ง€์ •ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

(5๋กœ ์ง€์ •ํ–ˆ์ง€๋งŒ ์›ํ•˜์‹œ๋Š” ํšŒ์ „๊ฐ’์„ ๋„ฃ์œผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.)

 

 func getAngle(p2:CGPoint) -> CGFloat {
        if p2.x <= center.x  {
            //1
            if p2.y <= center.y {
                return 5
            //3
            }else {
                return -5
            }
        }else {
            //2
            if p2.y <= center.y {
                return -5
            //4
            }else {
                return 5
            }
        }
    }

 

๊ทธ๋ฆฌ๊ณ  ๋ทฐ๋ฅผ ํšŒ์ „ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

func rotate(degrees: CGFloat) {
        let degreesToRadians: (CGFloat) -> CGFloat = { (degrees: CGFloat) in
            return degrees / 180.0 * CGFloat.pi
        }
        self.transform =  CGAffineTransform(rotationAngle: degreesToRadians(degrees))
    }

 

์•„๋ž˜์™€ ๊ฐ™์ด ๋“œ๋ž˜๊ทธ ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ ๋นจ๊ฐ„์ 2์˜ ์œ„์น˜์— ๋”ฐ๋ผ ๊ฐ๋„๋ฅผ ๊ตฌํ•ด ํšŒ์ „ํ•˜๊ณ 

 

๋“œ๋ž˜๊ทธ๊ฐ€ ๋๋‚  ๋•Œ ํšŒ์ „์„ 0๋„๋กœ ๋งŒ๋“ค์–ด ์ œ์ž๋ฆฌ๋กœ ๋Œ์•„์˜ค๊ฒŒ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

@objc func dragSquare(_ sender: UIPanGestureRecognizer) {
        if sender.state == .began {
            let location = sender.location(in: view)
            gap.x = square.center.x - location.x
            gap.y = square.center.y - location.y
            changeColor(.red)
            redDot1.center = location
        }else if sender.state == .changed {
            redDot2.center = sender.location(in: view)
            addLine(start: redDot1.center,end:redDot2.center)
            let distance:CGFloat = getTwoPointDistance(redDot1.center,redDot2.center)
            if distance > 100 {
                goal = square.getDestinationPoint(p2: redDot2.center)
                createDisplayLink()
                let angle:CGFloat = square.getAngle(p2:redDot2.center)
                rotateAndChangeColor(angle: angle, color: .systemRed)
            }
        }else if sender.state == .ended {
            changeColor(.clear)
            rotateAndChangeColor(angle: 0, color: .clear)
        }
    }

 

ํšŒ์ „๊ณผ ์ƒ‰์„ ๋ฐ”๊ฟ”์ค„ ๋•Œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ค˜์„œ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

private func rotateAndChangeColor(angle:CGFloat,color:UIColor) {
        UIView.animate(withDuration: 0.5) {
            self.square.rotate(degrees:angle)
            self.label.rotate(degrees:angle)
            self.changeColor(color)
        }
    }

 

์•„๋ž˜์™€ ๊ฐ™์ด ์ค„์„ ๋‹น๊ธฐ๋Š” ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ ์ƒ์ž๊ฐ€ ํšŒ์ „ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


์˜ค๋Š˜์€ ์ด๋ ‡๊ฒŒ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ๋””๋ฒจ๋กœํผ๋‹˜์˜ ํŠœํ† ๋ฆฌ์–ผ์„ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋Š”๋ฐ์š”.

 

๋ณด๊ธฐ์—” ์ •๋ง ๊ฐ„๋‹จํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋˜ ๊ฒƒ๋“ค์ด ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ•˜๋‹ˆ ์‹œ๊ฐ„๋„ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๊ณ  ๊ฝค ๋ณต์žกํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ด ํŠœํ† ๋ฆฌ์–ผ์„ ํ†ตํ•ด์„œ ๋‚˜๋ฆ„ ๋ฐฐ์šด ๊ฒƒ๋„ ๋งŽ๊ณ  ์˜ˆ์ „๋ถ€ํ„ฐ ํ•˜๊ณ ์‹ถ์—ˆ๋˜ ํฌ๋ฆฌ์—์ดํ‹ฐ๋ธŒ ์ฝ”๋”ฉ์ด๋ผ์„œ ๊ตฌํ˜„ํ•˜๊ณ  ๋‚˜๋‹ˆ ๋ฟŒ๋“ฏํ•˜๋„ค์š”...ใ…Žใ…Ž

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€