Skip to content

Instantly share code, notes, and snippets.

@mzsima
Created September 7, 2015 14:24
Show Gist options
  • Save mzsima/9aea6777f9dbf18966a1 to your computer and use it in GitHub Desktop.
Save mzsima/9aea6777f9dbf18966a1 to your computer and use it in GitHub Desktop.
manual ball feeder
//
// ViewController.swift
// ManualBallFeeder
//
// Created by MizushimaYusuke on 9/7/15.
// Copyright (c) 2015 MizushimaYusuke. All rights reserved.
//
import UIKit
import SceneKit
class ViewController: UIViewController, SCNSceneRendererDelegate {
weak var sceneView : SCNView?
var bumps : Array<SCNNode> = []
var speed : Float = 0
var preTouch : CGPoint = CGPointZero
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
createBallTube()
createLane()
chargeBall()
}
func setupScene() {
let sv = SCNView(frame: view.bounds)
sv.backgroundColor = UIColor(hue: 0.5, saturation: 0.05, brightness: 1, alpha: 1)
sv.scene = SCNScene()
sv.autoenablesDefaultLighting = true
view.addSubview(sv)
sv.delegate = self
sceneView = sv
}
func createBallTube() {
let tube = SCNTube(innerRadius: 0.9, outerRadius: 1.1, height: 5)
tube.firstMaterial?.diffuse.contents = UIColor.blueColor().colorWithAlphaComponent(0.2)
let box = SCNNode(geometry: tube)
box.position = SCNVector3(x: -5, y: 0.5, z: 0)
box.physicsBody = SCNPhysicsBody.staticBody()
box.physicsBody?.physicsShape = SCNPhysicsShape(node: box, options: [SCNPhysicsShapeTypeKey : SCNPhysicsShapeTypeConcavePolyhedron])
sceneView?.scene?.rootNode.addChildNode(box)
}
func createLane() {
let flat = SCNBox(width: 12, height: 0.1, length: 1, chamferRadius: 0)
flat.firstMaterial?.diffuse.contents = UIColor.grayColor()
let lane = SCNNode(geometry: flat)
lane.position = SCNVector3(x: 0, y: -3.5, z: 0)
lane.physicsBody = SCNPhysicsBody.staticBody()
lane.physicsBody?.friction = 0.8
sceneView?.scene?.rootNode.addChildNode(lane)
updateBumps()
let wall = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)
wall.firstMaterial?.diffuse.contents = UIColor.grayColor()
let wallNode = SCNNode(geometry: wall)
wallNode.position = SCNVector3(x: -6.5, y: -2.8, z: 0)
wallNode.physicsBody = SCNPhysicsBody.staticBody()
sceneView?.scene?.rootNode.addChildNode(wallNode)
}
func updateBumps() {
let bump = SCNBox(width: 0.1, height: 0.1, length: 1, chamferRadius: 0.05)
bump.firstMaterial?.diffuse.contents = UIColor.darkGrayColor()
for i in 0...11 {
let bumpyNode = SCNNode(geometry: bump)
bumpyNode.position = SCNVector3(x: Float(i) - 6, y: -3.4, z: 0)
bumpyNode.physicsBody = SCNPhysicsBody.dynamicBody()
bumpyNode.physicsBody?.angularVelocityFactor = SCNVector3Zero
self.sceneView?.scene?.rootNode.addChildNode(bumpyNode)
bumps.append(bumpyNode)
}
}
func chargeBall() {
let ball = SCNSphere(radius: 0.7)
ball.firstMaterial?.diffuse.contents = UIColor.yellowColor()
for i in 0...4 {
let ballNode = SCNNode(geometry: ball)
ballNode.position = SCNVector3(x: -5, y: Float(i) * 1.4, z: 0)
ballNode.physicsBody = SCNPhysicsBody.dynamicBody()
ballNode.physicsBody?.velocityFactor = SCNVector3(x: 1, y: 1, z: 0.01)
sceneView?.scene?.rootNode.addChildNode(ballNode)
}
}
func renderer(aRenderer: SCNSceneRenderer, didSimulatePhysicsAtTime time: NSTimeInterval) {
var needUpdate = false;
for i in 0..<self.bumps.count {
let b = self.bumps[i]
let vx = max(-1, min(1, b.physicsBody!.velocity.x + pow(Float(speed - b.physicsBody!.velocity.x), 3)))
b.physicsBody?.velocity = SCNVector3(x: vx, y: 0.1, z: 0)
b.physicsBody?.damping = 0
if (b.presentationNode().position.x >= 6) {
b.removeFromParentNode()
self.bumps.removeAtIndex(find(self.bumps, b)!)
let bump = SCNBox(width: 0.1, height: 0.1, length: 1, chamferRadius: 0.05)
bump.firstMaterial?.diffuse.contents = UIColor.darkGrayColor()
let bumpyNode = SCNNode(geometry: bump)
bumpyNode.position = SCNVector3(x: -6, y: -3.4, z: 0)
bumpyNode.physicsBody = SCNPhysicsBody.dynamicBody()
bumpyNode.physicsBody?.angularVelocityFactor = SCNVector3Zero
self.sceneView?.scene?.rootNode.addChildNode(bumpyNode)
self.bumps.insert(bumpyNode, atIndex: 0)
return
}
}
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
if let touch = touches.first as? UITouch {
let p = touch.locationInView(self.sceneView)
if p != CGPointZero {
self.speed = min(0.5 * fabs(Float(p.x) - Float(preTouch.x)), 1)
}
self.preTouch = p
}
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
self.speed = 0
}
}
extension Array {
func each(doit:T->Void) { for i in self { doit(i) } }
}
@mzsima
Copy link
Author

mzsima commented Sep 7, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment