Reputation: 75
Please help me to find a mistake.
I need each pad to play own sound from array, but only pads 13, 14, 15 does. At the same time i put a labels with node name on each pad, what tells that node has a name, so it looks like problem not in names and i cant catch what is it. If you have something else to say about improving this code, please feel free to say, i'm newbie and would be happy to hear.
What am i doing wrong?
Thanks
PS: And i want to say, im doing it on sprite kit just for challenge.
import SpriteKit
import GameplayKit
import AVFoundation
class GameScene: SKScene {
var i = 1
let sounds = ["Kick", "Clap","Hat","OpHat","Snare","Cow","Crash","Snap","Chant","Tom","11","12","13","14","15"]
override func didMove(to view: SKView) {
do {
for sound in sounds {
let player = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: Bundle.main.path(forResource: sound, ofType: "wav")!) as URL)
player.prepareToPlay()
}
} catch {
}
var frameHightMulti = CGFloat(0)
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
let tittleLabel = SKLabelNode(text: "Let the music play")
tittleLabel.fontSize = 50
tittleLabel.fontName = "Helvetica Nue"
tittleLabel.fontColor = UIColor.white
tittleLabel.position = CGPoint(x: 0, y: 600)
addChild(tittleLabel)
for _ in 1...5 {
var frameWidthMulti = CGFloat(0)
for _ in 1...3 {
let pad = SKSpriteNode(color: UIColor.cyan, size: CGSize(width: 220, height: 220))
pad.physicsBody = SKPhysicsBody(rectangleOf: pad.frame.size)
pad.position = CGPoint(x: -240 + frameWidthMulti, y: -500 + frameHightMulti)
pad.name = sounds[i-1]
let nameLabel = SKLabelNode(text: pad.name)
nameLabel.fontSize = 50
nameLabel.fontName = "Helvetica Nue"
nameLabel.fontColor = UIColor.black
nameLabel.position = pad.position
addChild(pad)
addChild(nameLabel)
frameWidthMulti += pad.size.width + 20
i += 1
}
frameHightMulti += 240
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touchLocation = touches.first?.location(in: self)
if let body = self.physicsWorld.body(at: touchLocation!){
if let z = body.node?.name {
switch z {
case "15":
self.run(SKAction.playSoundFileNamed("15", waitForCompletion: false))
print(z)
case "14":
self.run(SKAction.playSoundFileNamed("14", waitForCompletion: false))
print(z)
case "13":
self.run(SKAction.playSoundFileNamed("13", waitForCompletion: false))
print(z)
case "12":
self.run(SKAction.playSoundFileNamed("12", waitForCompletion: false))
print(z)
case "11":
self.run(SKAction.playSoundFileNamed("11", waitForCompletion: false))
print(z)
case "Tom":
self.run(SKAction.playSoundFileNamed("Tom", waitForCompletion: false))
print(z)
case "Crash":
self.run(SKAction.playSoundFileNamed("Crash", waitForCompletion: false))
print(z)
case "Snap":
self.run(SKAction.playSoundFileNamed("Snap", waitForCompletion: false))
print(z)
case "Chant":
self.run(SKAction.playSoundFileNamed("Chant", waitForCompletion: false))
print(z)
case "Cow":
self.run(SKAction.playSoundFileNamed("Cow", waitForCompletion: false))
print(z)
case "Snare":
self.run(SKAction.playSoundFileNamed("Snare", waitForCompletion: false))
print(z)
case "OpHat":
self.run(SKAction.playSoundFileNamed("OpHat", waitForCompletion: false))
print(z)
case "Hat":
self.run(SKAction.playSoundFileNamed("Hat", waitForCompletion: false))
print(z)
case "Clap":
self.run(SKAction.playSoundFileNamed("Clap", waitForCompletion: false))
print(z)
case "Kick":
self.run(SKAction.playSoundFileNamed("Kick", waitForCompletion: false))
print(z)
default: print("Shit hpns")
}
}
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
Upvotes: 2
Views: 89
Reputation: 10664
AVAudioPlayer is different to SKAction, so the do/catch method you are calling to prepare the AVAudioPlayer with your sound names is not needed. AVAudioPlayer is mainly used for background music.
So you can simply call the SKAction like you are already doing in the touches began method without any pre-setup. You would usually call them like so, with the correct file extension in the name.
run(SKAction.playSoundFileNamed("Kick.wav", waitForCompletion: false))
As a tip, you should create those sound actions as properties of your class so they are preloaded and ready to be used. If you just call the action directly in the touchesBegan method you will most likely see some lag/stutter when a sound file needs to preload for the first time.
Try something like this
enum SoundName: String { // store sound names like this to avoid typos
case kick = "Kick.wav"
case klap = "Klap.wav"
...
}
var sounds = [String: SKAction]()
var soundNames = [SoundName.kick.rawValue, SoundName.klap.rawValue, etc]
Than you set them up like this
func didMove(to view: SKView) {
for soundName in soundNames {
let soundAction = SKAction.playSoundFileNamed(sound, waitForCompletion: false)
sounds.updateValue(soundAction, forKey: soundName)
}
}
Than when you want to play them you can say this
if let sound = sounds[SoundName.kick.rawValue] { // safely unwrap dict value as it might not exist
run(sound)
}
Also make sure that when you create your sprites/pads that the node name is set up correctly otherwise the switch statement in touchesBegan will not work. Not sure why you are having 2 loops at that bit. Check that part and make sure your pads have the correct names, use print statements to see whats happening.
Try this as well in your touchesMethod.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
let node = atPoint(location)
if let nodeName = node.name {
switch nodeName {
case SoundName.kick.rawValue:
if let sound = sounds[SoundName.kick.rawValue] {
run(sound)
}
...
default:
break
}
}
}
Hope this helps
Upvotes: 1