- νλ‘μ νΈ κΈ°κ°: [2023λ 10μ 5μΌ ~ 10μ 6μΌ]
- νλ‘μ νΈ νμ: Whalesπ¬, Moonπ, Erickπ¦¦
- π μκ°
- π» μ€ν νλ©΄
- π οΈ μ¬μ© κΈ°μ
- π λ€μ΄μ΄κ·Έλ¨
- 𧨠νΈλ¬λΈ μν
κ°μ μ«μ λΈλμ 맀μΉμμΌ λ ν° μ«μλ₯Ό λ§λ€μ΄λ³΄μΈμ! λͺ©ν μ μ 1024! (λ¨, λΈλ ν©μ±μ μΈλ‘λ§ κ°λ₯!)
κ²μ μ€ν | κ²μ μ±κ³΅ | κ²μ μ€ν¨ |
---|---|---|
ꡬν λ΄μ© | λꡬ |
---|---|
μν€ν μ³ | MVC |
UI | UIKit |
μ λλ©μ΄μ | CoreAnimation |
π¨ λ¬Έμ μ
- λΈλμ΄ λ¨κ³μ μΌλ‘ μμ¬μμ λ, μ°μμ μΌλ‘ ν©μ±μ΄ λμ΄μΌ νλλ° μ μΌ μμ μλ λΈλλ§ ν©μ±λκ³ λ©μΆλ λ¬Έμ μ μ΄ λ°μνμμ΅λλ€.
(μλ₯Ό λ€μ΄, λΈλμ΄ μλλΆν° 4, 2 μμλ‘ μμ¬μκ³ 2λ₯Ό μΆκ°νλ©΄ 2+2=4, 4+4=8μ΄ λμ΄μ 8λΈλμ΄ λ¨μμΌ νλλ° 4λΈλ λ κ°κ° μμ¬μλ μνμμ λ©μΆλ νμ)
π‘ ν΄κ²°λ°©λ²
GameLogic
ν΄λμ€μvalidatePosition
λ©μλμμ λΈλμ΄ ν©μ³μ§λ©΄pointArray
λ₯Ό λ°ννλ©΄μ ν¨μμ ν¨κ» μλμΌλ‘ μ’ λ£λμλfor
λ¬Έμ λ μ΄μ ν©μ³μ§ λΈλμ΄ μμ λbreak
λ₯Ό νκ³ κ·Έ μΈλ κ°μ₯ μλμͺ½κΉμ§ λ°λ³΅ν μ μλλ‘ μ½λλ₯Ό μμ νμμ΅λλ€.
π μ½λ λ³ν
-
μμ μ
final class GameLogic { // ... func validatePosition(tappedX: CGFloat, block: BlockView) -> CGPoint { let (line, pointArray) = decideLine(tappedX: tappedX) for i in 0..<line.list.count-1 { if line.hasNext(i) { let nextBlockView = line.next(i) if compareBlockView(block, nextBlockView) { block.updateState() line.insert(block, at: i+1) nextBlockView.removeFromSuperview() return pointArray[i+1] } line.insert(block, at: i) return pointArray[i] } else if i == line.list.count-2 { line.insert(block, at: i+1) return pointArray[i+1] } } return validatePosition(tappedX: tappedX, block: block) }
-
μμ ν
final class GameLogic { // ... func validatePosition(tappedX: CGFloat, block: BlockView) -> CGPoint { let (line, pointArray) = decideLine(tappedX: tappedX) var value: CGPoint = CGPoint(x: 0, y: 0) for i in 0..<line.list.count-1 { if line.hasNext(i) { var nextBlockView = line.next(i) if compareBlockView(block, nextBlockView) == false { line.insert(block, at: i) value = pointArray[i] break } block.updateState() line.insert(block, at: i+1) if i < 5 { nextBlockView.removeFromSuperview() nextBlockView = line.next(i+1) } value = pointArray[i+1] } else if i == line.list.count-2 { line.insert(block, at: i+1) value = pointArray[i+1] break } } return value }
π¨ λ¬Έμ μ
- GameLogic λ΄ Lineμ λ°°μ΄λ‘λ§ κ΄λ¦¬νμ¬ λΆνμν μ½λκ° λ§μμ΅λλ€.
π‘ ν΄κ²°λ°©λ²
- BlockViewμ μ½μ λ° μμ κ΄λ¦¬λ₯Ό ν΄μ£Όλ Line κ°μ²΄ μμ±νμ¬ Lineμ μ½κ² κ΄λ¦¬νμ΅λλ€.
π μ½λ λ³ν
-
μμ μ
final class GameLogic { var line1: [Block?] = [nil, nil, nil, nil, nil, nil, nil] var line2: [Block?] = [nil, nil, nil, nil, nil, nil, nil] var line3: [Block?] = [nil, nil, nil, nil, nil, nil, nil] var line4: [Block?] = [nil, nil, nil, nil, nil, nil, nil] var line5: [Block?] = [nil, nil, nil, nil, nil, nil, nil] // ... }
-
μμ ν
final class Line { var list: [Block?] = [nil, nil, nil, nil, nil, nil, nil] func insert(_ block: Block,at index: Int) { list.insert(block, at: index) } func hasNext(_ index: Int) -> Bool { return list[index + 1] != nil } func next(_ index: Int) -> Block { return list[index + 1]! } }
final class GameLogic { var line1: Line = Line() var line2: Line = Line() var line3: Line = Line() var line4: Line = Line() var line5: Line = Line() // ... }
π¨ λ¬Έμ μ
- Controllerμμ μ¬μ©μ μ νμ λ§λ Block μ’νλ₯Ό μ°Ύλ λΆνμν λ‘μ§μ μννμ΅λλ€.
π‘ ν΄κ²°λ°©λ²
- GameLogicμ΄ μ¬μ©μ μ νμ λ§λ Lineμ μ°Ύμ Block μ’νλ₯Ό λ°ννλλ‘ λ³κ²½νμ¬, Controllerμμ GameLogic.validatePositionλ₯Ό νΈμΆνμ¬ Blockμ μ’νλ₯Ό μ€μ νλλ‘ νμ΅λλ€.
π μ½λ λ³ν
-
μμ μ
class ViewController: UIViewController { // ... @objc private func didTappedGridView() { let tappedPointX = tapGestureRecognizer.location(in: view).x if tappedPointX >= 23, tappedPointX < 93 { block.x = 23 } else if tappedPointX >= 93, tappedPointX < 163 { block.x = 93 } else if tappedPointX >= 163, tappedPointX < 233 { block.x = 163 } else if tappedPointX >= 233, tappedPointX < 303 { block.x = 233 } else { block.x = 303 } } }
-
μμ ν
final class GameLogic { // ... func decideLine(tappedX: CGFloat) -> (Line, [CGPoint]) { if tappedX < 95 { return (line1, pointArray1) } else if tappedX >= 95, tappedX < 163 { return (line2, pointArray2) } else if tappedX >= 163, tappedX < 231 { return (line3, pointArray3) } else if tappedX >= 231, tappedX < 299 { return (line4, pointArray4) } else { return (line5, pointArray5) } } func validatePosition(tappedX: CGFloat, block: BlockView) -> CGPoint { let (line, pointArray) = decideLine(tappedX: tappedX) var value: CGPoint = CGPoint(x: 0, y: 0) // point finding logic return value } }
class ViewController: UIViewController { // ... @objc private func didTappedGridView() { let tappedPointX = tapGestureRecognizer.location(in: view).x let point = gameLogic.validatePosition(tappedX: tappedPointX, block: blockView.blockState) blockView.frame.origin = point } }
π¨ λ¬Έμ μ
- κΈ°λ³Έμ μΌλ‘ λΈλμ΄ μμ±λ λ μμΉμ λ°λ‘ λνλκΈ° λλ¬Έμ λΈλμ΄ μ¬λ¬ κ° μμ¬μμ κ²½μ° λΈλμ΄ μμ±λμλμ§ μΈμνκΈ° νλ€λ€λ λ¬Έμ κ° μμ΅λλ€. μ΄λ¬ν μ¬μ©μ κ²½νμ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ λΈλ μμ± μ λμ λκ² λ§λ€ λ°©λ²μ΄ νμνμ΅λλ€.
π‘ ν΄κ²°λ°©λ²
- λΈλ μμ± μ μ λλ©μ΄μ μ μΆκ°ν΄ λμ λκ³ λ³΄κΈ° μ’κ² λ§λ€μ΄ μ¬μ©μ κ²½νμ κ°μ νμ΅λλ€.
π μ½λ λ³ν
-
μ λλ©μ΄μ μΆκ°
func runSpringAnimation() { let jump = CASpringAnimation(keyPath: "transform.scale") jump.damping = 15 jump.mass = 1 jump.initialVelocity = 10 jump.stiffness = 100 jump.fromValue = 0 jump.toValue = 1 jump.duration = jump.settlingDuration self.layer.add(jump, forKey: nil) }