Skip to content

Instantly share code, notes, and snippets.

@GuyCarver
Created September 23, 2016 03:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GuyCarver/465e95dfac21e1a101a3eeb3c81c662d to your computer and use it in GitHub Desktop.
Save GuyCarver/465e95dfac21e1a101a3eeb3c81c662d to your computer and use it in GitHub Desktop.
F# version of pong.cs example for Continuous app. Only partially implemented due to some bugs in the app.
//
// Pong Example
//
// Implements a basic version of the classic game for two players.
// Swipe up and down on the left to move the left paddle, and
// swipe on the right side for the right paddle.
//
// Tip: If the editor freezes while you type,
// turn off "Auto Run" in the settings.
//
// Exercises:
// 1. Change the color of the ball to green
// 2. Change the size of the paddles
// 3. Make the ball move faster
// 4. Add multiple balls
// 5. Add an AI to control the second paddle
//
open System
open CoreGraphics
open SceneKit
open UIKit
[<NoComparison>]
type PongDefaults = {
BallSize : float //= 5.0f;
BallColor : UIColor //= UIColor.Yellow;
BallRestitution : float //= 2.01f;
LeftPaddleHeight : nfloat //= 30.0f;
RightPaddleHeight : nfloat //= 30.0f;
}
let defaults = { BallSize = 5.0; BallColor = UIColor.Yellow; BallRestitution = 2.01;
LeftPaddleHeight = nfloat(30.0); RightPaddleHeight = nfloat(30.0) }
type Ball =
val mutable Node : SCNNode
new ( ) as self =
{
Node = null
}
then
let geom = SCNSphere.Create(nfloat(defaults.BallSize))
geom.FirstMaterial.Diffuse.ContentColor <- defaults.BallColor
self.Node <- SCNNode.FromGeometry(geom)
// Attach a light to the ball
let ln = SCNNode.Create()
ln.Light <- SCNLight.Create()
ln.Position <- SCNVector3(0.0f,0.0f,float32(defaults.BallSize) * 4.0f)
self.Node.Add ln
// Add physics to the ball
self.Node.PhysicsBody <- SCNPhysicsBody.CreateDynamicBody()
self.Node.PhysicsBody.Damping <- nfloat(0.0)
self.Node.PhysicsBody.Friction <- nfloat(0.0)
self.Node.PhysicsBody.Restitution <- nfloat(defaults.BallRestitution)
let options = SCNPhysicsShapeOptions()
self.Node.PhysicsBody.PhysicsShape <- SCNPhysicsShape.Create(geom, options)
self.Node.PhysicsBody.CategoryBitMask <- nuint(1u)
self.Node.PhysicsBody.CollisionBitMask <- nuint(1u)
self.Node.PhysicsBody.ContactTestBitMask <- nuint(1u)
type Paddle =
val mutable Node : SCNNode
new ((x : float32), (h : nfloat)) as self =
{
Node = null
}
then
let geom = SCNBox.Create(nfloat(4.0), h, nfloat(20.0), nfloat(0.0))
geom.FirstMaterial.Diffuse.ContentColor <- UIColor.LightGray
geom.FirstMaterial.Specular.ContentColor <- UIColor.Yellow
geom.FirstMaterial.Specular.Intensity <- nfloat(1.0)
self.Node <- SCNNode.FromGeometry(geom)
self.Node.Position <- SCNVector3(x,0.0f,0.0f)
self.Node.PhysicsBody <- SCNPhysicsBody.CreateStaticBody()
let options = SCNPhysicsShapeOptions()
self.Node.PhysicsBody.PhysicsShape <- SCNPhysicsShape.Create(geom, options)
self.Node.PhysicsBody.CategoryBitMask <- nuint(1u)
self.Node.PhysicsBody.CollisionBitMask <- nuint(1u)
self.Node.PhysicsBody.ContactTestBitMask <- nuint(1u)
type Wall =
val mutable Node : SCNNode
new (y : float32) as self =
{
Node = null
}
then
let geom = SCNBox.Create(nfloat(320.0), nfloat(4.0), nfloat(15.0), nfloat(0.0))
geom.FirstMaterial.Diffuse.ContentColor <- UIColor.DarkGray
geom.FirstMaterial.Specular.ContentColor <- UIColor.Yellow
geom.FirstMaterial.Specular.Intensity <- nfloat(1.0)
self.Node <- SCNNode.FromGeometry(geom)
self.Node.Position <- SCNVector3(0.0f,y,0.0f)
self.Node.PhysicsBody <- SCNPhysicsBody.CreateStaticBody()
let options = SCNPhysicsShapeOptions()
self.Node.PhysicsBody.PhysicsShape <- SCNPhysicsShape.Create(geom, options)
self.Node.PhysicsBody.CategoryBitMask <- nuint(1u)
self.Node.PhysicsBody.CollisionBitMask <- nuint(1u)
self.Node.PhysicsBody.ContactTestBitMask <- nuint(1u)
type Goal =
val mutable Node : SCNNode
new (x : float32) as self =
{
Node = null
}
then
let geom = SCNBox.Create(nfloat(6.0), nfloat(400.0), nfloat(20.0), nfloat(0.0))
geom.FirstMaterial.Diffuse.ContentColor <- UIColor.Black
self.Node <- SCNNode.FromGeometry(geom)
self.Node.Position <- SCNVector3(x,0.0f,0.0f)
self.Node.PhysicsBody <- SCNPhysicsBody.CreateKinematicBody()
let options = SCNPhysicsShapeOptions()
self.Node.PhysicsBody.PhysicsShape <- SCNPhysicsShape.Create(geom, options)
self.Node.PhysicsBody.CategoryBitMask <- nuint(1u)
self.Node.PhysicsBody.CollisionBitMask <- nuint(1u)
self.Node.PhysicsBody.ContactTestBitMask <- nuint(1u)
type Camera () =
let camera = SCNCamera.Create()
let _node = SCNNode.Create()
do
_node.Camera <- camera
_node.Position <- SCNVector3 (0.0f,0.0f,150.0f)
camera.ZNear <- 1.0
camera.ZFar <- 150.0
// Attach a light to the camera
let ln = SCNNode.Create()
ln.Light <- SCNLight.Create()
ln.Position <- SCNVector3(0.0f,0.0f,50.0f)
_node.Add ln
member x.Node with get() = _node
//
// Create the game
//
let mutable playerScore = 0
let mutable aiScore = 0
let cam = Camera()
let ball = Ball()
let playerPaddle = Paddle(-90.0f, defaults.LeftPaddleHeight)
let aiPaddle = Paddle(90.0f, defaults.RightPaddleHeight)
let topWall = Wall(70.0f)
let botWall = Wall(-70.0f)
let playerGoal = Goal(-130.0f)
let aiGoal = Goal(130.0f)
let scoreLabel : UILabel = new UILabel()
scoreLabel.Text <- "0 : 0"
scoreLabel.TextAlignment <- UITextAlignment.Center
scoreLabel.Font <- UIFont.SystemFontOfSize(nfloat(100.0))
scoreLabel.TextColor <-UIColor.White.ColorWithAlpha(nfloat(0.25))
scoreLabel.AutoresizingMask <- UIViewAutoresizing.FlexibleDimensions
scoreLabel.AdjustsFontSizeToFitWidth <- true
//
// Create the view
//
let scene = SCNScene.Create()
scene.PhysicsWorld.Gravity <- SCNVector3.Zero
let root = scene.RootNode
let UpdateScore () =
scoreLabel.BeginInvokeOnMainThread(fun () ->
scoreLabel.Text <- "{playerScore} : {aiScore}"
)
let sceneView = new SCNView(CGRect(nfloat(0.0),nfloat(0.0),nfloat(320.0),nfloat(320.0)))
sceneView.BackgroundColor <- UIColor.Black
sceneView.Scene <- scene
scoreLabel.Frame <- sceneView.Bounds
sceneView.AddSubview(scoreLabel)
root.Add(cam.Node)
root.Add(ball.Node)
root.Add(playerPaddle.Node)
root.Add(aiPaddle.Node)
root.Add(topWall.Node)
root.Add(botWall.Node)
root.Add(playerGoal.Node)
root.Add(aiGoal.Node)
sceneView.PointOfView <- cam.Node
let rand = Random()
let ResetBallPosition (x : float32) =
printfn "resetting"
let mutable vx = float32(rand.NextDouble()) * 75.0f + 75.0f
let mutable vy = float32(rand.NextDouble()) * 50.0f + 50.0f
if (x > 0.0f) then vx <- -vx
if (rand.Next(2) = 0) then vy <- -vy
ball.Node.Position <- SCNVector3(x, 0.0f, 0.0f)
match ball.Node.PhysicsBody with
| null -> printfn "null pb"
| x -> x.Velocity <- SCNVector3(vx, vy, 0.0f)
x.ResetTransform()
ResetBallPosition(0.0f)
(* causing exception.
scene.PhysicsWorld.DidBeginContact.Add( (e : SCNPhysicsContactEventArgs) ->
ResetBallPosition 0
//let otherNode = match bal.node with
//| e.Contact.NodeA -> e.Contact.NodeB
//| e.Contact.NodeB -> e.Contact.NodeA
//| _ -> null
//ignore(match othernode with
//| playerGoal.Node ->
//Console.WriteLine("HIT PLAYER");
// aiScore <- aiScore + 1
// ResetBallPosition 50
// UpdateScore()
//| aiGoal.Node ->
//Console.WriteLine("HIT AI");
// playerScore <- playerScore + 1
// ResetBallPosition -50
// UpdateScore()
//| _ -> ()
//)
//e.Contact.NodeA.Geometry.FirstMaterial.Diffuse.ContentColor=UIColor.Red;
)
*)
let panGesture = new UIPanGestureRecognizer (fun (g : UIPanGestureRecognizer) ->
match int(g.NumberOfTouches) with
| 0 -> ()
| n ->
for i in 0 .. n do
let viewLoc = g.LocationOfTouch(nint(i), sceneView)
let a = viewLoc.X
let b = viewLoc.Y
let p = sceneView.UnprojectPoint SCNVector3(float32(a), float32(b), 1.0f)
//printfn "%d:%s" i p.ToString()
//this causes and exception cuz X isn't accessible for some reason.
if p.X < 0.0f then
playerPaddle.Node.Position <- SCNVector3(-90.0f, p.Y, 0.0f)
playerPaddle.Node.PhysicsBody.ResetTransform()
else
aiPaddle.Node.Position <- SCNVector3(90.0f, p.Y, 0.0f)
aiPaddle.Node.PhysicsBody.ResetTransform()
)
let tapGesture = new UITapGestureRecognizer (fun (g : UITapGestureRecognizer) -> ResetBallPosition float32(0.0) )
tapGesture.NumberOfTapsRequired <- nuint(2u)
sceneView.AddGestureRecognizer(panGesture)
sceneView.AddGestureRecognizer(tapGesture)
let Main = sceneView
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment