Swift: SpriteKitAudio 예제 (AudioKit)
Swift: SpriteKitAudio 예제 (AudioKit)
Sprite Kit Audio
이 코드는 SpriteKit과 AudioKit을 결합한 인터랙티브 사운드 예제입니다. 사용자가 화면을 터치하면 공이 생성되고, 플랫폼에 부딪히면 소리가 나는 구조입니다. 주요 구성요소별로 설명드리겠습니다.
전반적 구조
SpriteKit을 이용해 물리 기반 애니메이션 처리AudioKit을 이용해 플랫폼에 충돌 시 음향 재생SwiftUI에서SpriteView로 SpriteKit 장면을 보여줌
1. GameScene (SKScene + 물리 처리)
didMove(to:)
- 장면 초기 설정
physicsWorld.contactDelegate = self→ 충돌 감지 델리게이트 설정physicsBody = edgeLoopFrom:→ 화면 가장자리를 물리적으로 막는 테두리 벽 생성for i in 1...3→ 3개의 경사진 **플랫폼(plat)**을 생성하고 물리 바디 설정
각 플랫폼 설정
- 회전각
.pi / 8,-.pi / 8을 사용해 경사 조절 categoryBitMask = 2,contactTestBitMask = 2로 충돌 범주 설정isDynamic = false로 고정된 물체 (움직이지 않음)
2. touchesBegan(_:with:)
-
사용자가 화면을 터치하면:
- 반지름 5짜리 원형 공(
box) 생성 - 랜덤한 색상 적용
- 해당 위치에 공 생성 후 중력 적용 (
affectedByGravity = true) - category와 contact 비트마스크도 2번으로 설정 → 플랫폼과 충돌 감지 가능
- 반지름 5짜리 원형 공(
3. didBegin(_:)
-
공이 플랫폼에 닿을 때:
platform1→ MIDI note 60platform2→ MIDI note 64platform3→ MIDI note 67- → 각각 다른 음을 재생 (도, 미, 솔)
-
그 외 바닥에 닿으면
ball노드를 제거
4. playSound(noteNumber:)
MIDISampler를 이용해 해당 note를 0.1초 동안 연주 후 중지
5. SpriteKitAudioConductor
MIDISampler를 AudioKit에서 초기화.exs사운드폰트 로딩 (e.g. sawPiano1.exs)Reverb로 출력 노드 감쌈 → 약간의 공간감 제공
6. SpriteKitAudioView (SwiftUI)
GameScene을 SpriteView에 넣어 SwiftUI에서 표시conductor를 장면에 주입.onAppear/.onDisappear로 AudioKit 엔진 제어
동작 흐름 요약
- 화면 터치 → 공 생성 → 중력에 의해 하강
- 공이 플랫폼에 닿으면 → 해당 음 재생
- 바닥에 닿으면 → 공 제거
SpriteKit 부분 상세
SpriteKit 부분은 이 프로젝트에서 그래픽과 물리 시뮬레이션을 담당하며, 주로 GameScene 클래스 내에서 구성됩니다. 각 구성 요소를 더 구체적으로 설명드리겠습니다.
GameScene 구성 요소 상세
didMove(to:)
SpriteKit 장면이 화면에 처음 표시될 때 호출되는 메서드입니다. 여기서 물리 월드 설정과 플랫폼 배치를 합니다.
주요 구성:
1
physicsWorld.contactDelegate = self
→ 물리 충돌 이벤트를 감지하기 위해 SKPhysicsContactDelegate 프로토콜을 채택하고, 해당 delegate를 자기 자신으로 지정합니다.
1
physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
→ 화면 전체를 테두리로 감싸는 물리 벽 생성. 공이 밖으로 나가지 않도록 함.
1
2
3
4
for i in 1...3 {
...
addChild(plat)
}
→ 경사진 3개의 플랫폼을 반복문으로 생성. 각 플랫폼은 SKShapeNode로 구성되고, 물리 바디가 설정됩니다.
각 플랫폼의 설정:
1
2
3
4
5
plat.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 80, height: 10))
plat.physicsBody?.isDynamic = false
plat.physicsBody?.affectedByGravity = false
plat.physicsBody?.categoryBitMask = 2
plat.physicsBody?.contactTestBitMask = 2
- isDynamic = false → 위치가 고정되어 물리 반응은 있지만, 움직이지 않음
- categoryBitMask & contactTestBitMask → 충돌 감지 대상 설정 (같은 그룹끼리 감지 가능)
touchesBegan(_:with:)
사용자가 화면을 터치하면 호출되는 메서드입니다.
- 원형
SKShapeNode(box)를 생성 - 터치 위치에 배치
- 중력 영향을 받도록 설정 (
affectedByGravity = true) - 충돌 감지를 위해 물리 바디 설정
예:
1
2
3
4
5
let box = SKShapeNode(circleOfRadius: 5)
box.physicsBody = SKPhysicsBody(circleOfRadius: 5)
box.physicsBody?.affectedByGravity = true
box.physicsBody?.categoryBitMask = 2
box.physicsBody?.contactTestBitMask = 2
이 공은 중력으로 낙하하며, platform과 category 설정이 같기 때문에 충돌 시 didBegin(_:) 호출됨.
didBegin(_ contact: SKPhysicsContact)
SpriteKit의 충돌 이벤트가 발생했을 때 자동 호출되는 메서드입니다.
contact.bodyA와contact.bodyB를 통해 어떤 노드끼리 충돌했는지 확인- 충돌한 platform이 어떤 것인지에 따라 다른 MIDI 노트(60, 64, 67)를 재생
또한, 특정 노드가 바닥이나 화면 하단에 닿은 경우 제거 처리도 여기에 포함될 수 있습니다.
SpriteKit에서 이 예제가 하는 일 요약
| 구성 요소 | 역할 |
|---|---|
SKScene |
물리 공간 (게임 보드 같은 역할) |
SKPhysicsWorld |
중력과 충돌 계산 수행 |
SKShapeNode |
공 및 플랫폼 노드의 시각적 표현 |
SKPhysicsBody |
실제 물리 연산을 담당하는 요소 |
categoryBitMask, contactTestBitMask |
충돌 범주 정의 및 감지 설정 |
touchesBegan |
공 생성 및 사용자 입력 반응 |
didBegin |
충돌 시 사운드 재생 로직 실행 |
This post is licensed under
CC BY 4.0
by the author.