출처 https://developer.apple.com/documentation/spritekit/
나는 이번에 SpriteKit
을 처음 들었다. 그게 iOS 개발자라고 할 수 있냐고 물으면 할 말 없다. 하여튼 이걸 공부하게 되었는데.. 0 상태에서 혼자 시작하려니 막막하다. 영어로 공부해야 한다는 번거로움은 덤이다. 그래서 내가 제일 좋아하는 무작정 따라 만들어보면서 체득하기 방법으로 해보려 한다. 유튜브에 퍼즐 게임 만드는 영상이 있길래 따라 만들어보면서 공부하는 과정을 포스팅으로 담아보려 한다.
그래도 공식문서조차 안보고 시작하는 건 좀 아닌 거 같아서 들어가보았다.
왜 Sprite
일까? 싶었다. 영영사전에 나오는 정의는 이렇다.
a computer graphic which may be moved on-screen and otherwise manipulated as a single entity
컴퓨터 그래픽이나 게임 개발에서 사용하는 특정 개념으로, 스프라이트
라고 영어 단어 그대로 용어로 쓰이는 경우가 많다고 한다. 나는 겜알못에다가 게임 개발 쪽에도 문외한이다 보니 처음 들어본 개념이었다. 그래픽 객체, 화면 객체, 애니메이션 요소 정도의 느낌인 것 같다.
공식문서에 따르면, SpriteKit
은 2D 게임 및 그래픽 개발을 위해 애플이 제공하는 프레임워크다. iOS
, macOS
, watchOS
, tvOS
, visionOS
환경에서의 게임을 개발하는 데 사용하며, GameplayKit
및 SceneKit
과 같은 프레임워크와 잘 통합된다.
2차원에서의 도형, 입자, 텍스트, 이미지, 비디오를 그리기 위한 범용 프레임워크로써, Metal
을 활용하여 고성능 렌더링을 구현한다. (여기서 Metal
은 나도 처음 들어봤는데 애플이 제공하는 저수준 그래픽 계산 API라고 한다) 또, 간단한 프로그래밍 인터페이스를 통해 게임 및 그래픽 요소를 쉽게 만들 수 있다.
이제 SpriteKit
의 주요 클래스들을 살펴보겠다.
An object that organizes all of the active SpriteKit content.
SpriteKit
의 근본적인 요소라고 할 수 있다. 실제로 고양이 퍼즐 게임을 만들어보니 코드의 90% 정도가 SKScene
클래스에 들어가있었다.
이름 그대로 scene(장면)
을 만드는 데 사용한다. 씬은 SKNode
로 만드는 node
들의 root node
다. (잘 모르지만 자료구조 트리 개념인 느낌이 든다) 노드들은 씬의 애니메이션이나 렌더링을 구성하는 요소들을 제공한다. 참고로, SKScene
은 SKNode
의 서브 클래스인 SKEffectNode
를 상속한다.
씬을 화면에 띄우기 위해서는 SKView
나 SKRenderer
, WKInterfaceSKScene (WatchOS 용)
를 통해야 한다.
나는 이번 실습에
SwiftUI
를 사용하는데,SwiftUI
에서는SpriteView(scene:)
를 통해scene
을 띄울 수 있다.
struct ContentView: View {
var scene: SKScene = GameScene()
var body: some View {
SpriteView(scene: scene)
.ignoresSafeArea()
}
}
A view subclass that renders a SpriteKit scene.
UIKit
에서 scene
을 화면에 표시하는 데 사용한다. presentScene(_:)
메소드를 호출하면 된다.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let containerView: SKView = SKView(frame: view.bounds)
containerView.presentScene(GameScene())
view.addSubview(containerView)
}
}
SKView
가 scene
을 표시할 때 scene
은 2가지 작업을 반복 수행한다.
scene
을 일시정지 하기 위해서는 SKView
의 isPaused
속성을 true
로 설정하여 두 작업을 중단시키면 된다. (쉬운 말로 게임을 일시정지하거나 특정 장면의 애니메이션을 멈추고 싶을 때 사용한다고 한다)
The base class of all SpriteKit nodes.
위에서 SKScene
또한 노드에 속한다고 말한 바 있다. 노드는 SpriteKit
의 모든 화면 요소라고 보면 될 거 같다. 모든 시각적, 논리적 객체는 SKNode
를 상속한다.
UIKit
으로 따지면 UIView
느낌? SKNode
에 속한 서브클래스들은 UIView
의 서브클래스인 뷰 컴포넌트들인 셈이다. (이건 내가 편의상 이해한 방식이고 공식문서에 나오는 표현은 아니다) 다만 단순히 화면을 그리는 요소 뿐만 아니라 효과를 내는 요소들도 있다. (ex. SKEmitterNode
: 입자 효과(불꽃, 연기, 비 등)를 만들 때 사용)
https://developer.apple.com/documentation/spritekit/nodes-for-scene-building
공식문서에 들어가보면 여러가지 노드 종류를 볼 수 있다. 고양이 퍼즐 게임에서는 이미지를 그리는 노드인 SKSpriteNode
를 주로 사용했다.
An image, decoded on the GPU, that can be used to render various SpriteKit objects.
SKTexture
는 이미지 데이터를 GPU에 효율적으로 로드하고, 렌더링 시 사용하는 객체다. SKSpriteNode
와 같은 노드가 화면에 이미지를 표시하려면 SKTexture
가 필요하다. SKTexture
는 이 이미지 데이터를 관리한다.
let texture = SKTexture(imageNamed: "cheese")
let cheeseNode = SKSpriteNode(texture: texture)
An object that is run by a node to change its structure or content.
액션. 쉽게 말해 애니메이션이다. 노드의 애니메이션 및 동작을 정의한다. 이동하기, 회전하기, 크기 변경 효과, 페이드 효과, 소리 재생 등을 생성하고 실행할 수 있다.
let moveAction = SKAction.move(to: CGPoint(x: 100, y: 100), duration: 2.0)
node.run(moveAction)
솔직히 아무리 말로 해도 와닿지가 않는다. 만들면서 실감해보자.
출처 - https://youtu.be/lYgipMRr7ws?si=k9tk3iYBI1MRFyLc
일단 내가 따라 만들기로 한 게임은 이렇게 생겼다. 똑같은 애들끼리 뭉쳐있는 부분을 눌러서 없애는 게임이다. 이미지 제공이 안되기도 하고, 나는 좀더 귀엽게 만들고 싶어서 지피티를 활용해 따로 이미지를 생성하여 프로젝트에 사용했다.
귀엽죠?
SKScene
클래스의 메소드들 중 didMove
를 활용한다. didMove
는 scene
이 view
에 의해 띄워졌을 때 호출되는 함수다. 이 시점에 배경화면 이미지 노드를 만들어 씬에 addChild
를 해주면 된다. (UIKit
에서 addSubview
하던 게 생각났다)
size
를 지정해주는 것이다. 기본값이 zero
기 때문에 이걸 안해주면 아무리 노드를 열심히 만들어서 넣어도 화면에 나오지가 않는다. (이걸로 트러블 겪음)class GameScene: SKScene {
override func didMove(to view: SKView) {
// scene 크기를 view의 크기와 똑같이 지정 (화면을 꽉 채울 거니까)
self.size = view.bounds.size
// 배경화면 이미지 노드 생성
let background = SKSpriteNode(imageNamed: "background")
background.position = CGPoint(x: size.width / 2, y: size.height / 2)
background.zPosition = -1 // 다른 노드들보다 뒤에 위치하기 위함
background.size = size // 노드 크기를 scene 크기와 같게 지정
addChild(background)
}
}
SpriteKit
에서 (0, 0)
좌표의 위치는 bottom-leading
이다. (UIKit
에서는 top-leading
이던 것과 비교된다.)anchor point
는 스스로의 중심점이다. (가장자리가 아니다) 그래서 position
을 지정할 때 size의 절반
만큼 더 이동시켜준 것이다.(0, 0)으로 position 했을 때 화면
(width / 2, height / 2)로 position 했을 때 화면
배경 하나 넣는 데도 트러블을 겪으며 SKScene
과 SKSpriteNode
에 대해 몇가지를 깨달았다. 역시 나는 직접 만들면서 배우는 게 잘 맞는다. 다음엔 고양이가 등장할 것이다.