I want to make a 3d game on Xcode, SceneKit. To test it out, I started a simple project about a box, that if you tapped, moves in X direction. My question is how do you make the tap gesture work in a 3d game? I've been trying to add it but it just doesn't work. Here is all the code that I've written in case I'm doing something wrong:
import UIKit
import QuartzCore
import SceneKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene(named:"art.scnassets/Box.scn")
let newscene = self.view as! SCNView
newscene.scene = scene
let tap = UITapGestureRecognizer(target: self, action: #selector(taps(tap:)));newscene.addGestureRecognizer(tap)
tap.numberOfTapsRequired = 1
tap.numberOfTouchesRequired = 1
}
override var shouldAutorotate: Bool {
return true
}
override var prefersStatusBarHidden: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
@objc func taps(tap:UITapGestureRecognizer){
let newscene = self.view as! SCNView
let scene = SCNScene(named: "art.scnassets/Box.scn")
let box = scene?.rootNode.childNode(withName: "Box", recursively: true)
let place = tap.location(in: newscene)
let tapped = newscene.hitTest(place, options: [:])
if tapped.count > 0{
box?.runAction(SCNAction.repeatForever(SCNAction.moveBy(x: 5, y: 0, z: 0, duration: 1)))
}
}
}
Try this...
@objc func handleTap(recognizer: UITapGestureRecognizer)
{
if(data.isNavigationOff == true) { return } // No panel select if Add, Update, EndWave, or EndGame
if(gameMenuTableView.isHidden == false) { return } // No panel if game menu is showing
let location: CGPoint = recognizer.location(in: gameScene)
if(data.isAirStrikeModeOn == true)
{
let projectedPoint = gameScene.projectPoint(SCNVector3(0, 0, 0))
let scenePoint = gameScene.unprojectPoint(SCNVector3(location.x, location.y, CGFloat(projectedPoint.z)))
gameControl.airStrike(position: scenePoint)
}
else
{
let hitResults = gameScene.hitTest(location, options: hitTestOptions)
for vHit in hitResults
{
if(vHit.node.name?.prefix(5) == "Panel")
{
// May have selected an invalid panel or auto upgrade was on
if(gameControl.selectPanel(vPanel: vHit.node.name!) == false) { return }
return
}
}
}
}
If Airstrike - Tap drops a bomb on the screen where you touched, translating it to 3D
Else hittest looks for panels which may return multiple results