SpriteKitAudio 예제
SpriteKitAudio 예제
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.