public Slide () { ContentNode = SCNNode.Create (); GroundNode = SCNNode.Create (); ContentNode.AddChildNode (GroundNode); TextManager = new SlideTextManager (); ContentNode.AddChildNode (TextManager.TextNode); // Default parameters LightIntensities = new float[] { 0.0f, 0.9f, 0.7f }; MainLightPosition = new SCNVector3 (0, 3, -13); EnableShadows = false; FloorImageName = null; FloorImageExtension = null; FloorReflectivity = 0.25f; FloorFalloff = 3.0f; TransitionDuration = 1.0f; TransitionOffsetX = 0.0f; TransitionOffsetZ = 0.0f; TransitionRotation = 0.0f; Altitude = 5.0f; Pitch = 0.0f; IsNewIn10_10 = false; }
SCNVector3 LocationAlongPath(nfloat percent) { if (PathPositions.Count <= 3) { return(SCNVector3.Zero); } int numSections = PathPositions.Count - 3; nfloat dist = percent * numSections; int currentPointIndex = (int)Math.Min((uint)Math.Floor(dist), numSections - 1); dist -= currentPointIndex; var a = new SCNVector3(PathPositions [currentPointIndex]); var b = new SCNVector3(PathPositions [currentPointIndex + 1]); var c = new SCNVector3(PathPositions [currentPointIndex + 2]); var d = new SCNVector3(PathPositions [currentPointIndex + 3]); var location = new SCNVector3(); location.X = CatmullRomValue(a.X, b.X, c.X, d.X, dist); location.Y = CatmullRomValue(a.Y, b.Y, c.Y, d.Y, dist); location.Z = CatmullRomValue(a.Z, b.Z, c.Z, d.Z, dist); return(location); }
public static SCNMatrix4 TranslateWithVector (this SCNMatrix4 matrix, SCNVector3 vector) { matrix.M41 += matrix.M11 * vector.X + matrix.M21 * vector.Y + matrix.M31 * vector.Z; matrix.M42 += matrix.M12 * vector.X + matrix.M22 * vector.Y + matrix.M32 * vector.Z; matrix.M43 += matrix.M13 * vector.X + matrix.M23 * vector.Y + matrix.M33 * vector.Z; return matrix; }
public static HitTestRay HitTestRayFromScreenPos(this ARSCNView self, CGPoint point) { if (self.Session == null || ViewController.CurrentFrame == null) { return(null); } var frame = ViewController.CurrentFrame; if (frame == null || frame.Camera == null || frame.Camera.Transform == null) { return(null); } var cameraPos = SCNVector3Extensions.PositionFromTransform(frame.Camera.Transform); // Note: z: 1.0 will unproject() the screen position to the far clipping plane. var positionVec = new SCNVector3((float)point.X, (float)point.Y, 1.0f); var screenPosOnFarClippingPlane = self.UnprojectPoint(positionVec); var rayDirection = screenPosOnFarClippingPlane.Subtract(cameraPos); rayDirection.Normalize(); return(new HitTestRay(cameraPos, rayDirection)); }
private void ShowCodeExample(string code, string imageName, string extension) { SCNTransaction.Begin(); SCNTransaction.AnimationDuration = 0; TextManager.FadeOutText(SlideTextManager.TextType.Code); if (code != null) { var codeNode = TextManager.AddCode(code); SCNVector3 min, max; min = new SCNVector3(0, 0, 0); max = new SCNVector3(0, 0, 0); codeNode.GetBoundingBox(ref min, ref max); if (imageName != null) { SCNNode imageNode = Utils.SCPlaneNode(NSBundle.MainBundle.PathForResource("Scenes/earth/" + imageName, extension), 4.0f, false); imageNode.Position = new SCNVector3(max.X + 2.5f, min.Y + 0.2f, 0); codeNode.AddChildNode(imageNode); max.X += 4.0f; } codeNode.Position = new SCNVector3(6 - (min.X + max.X) / 2, 10 - min.Y, 0); } SCNTransaction.Commit(); }
public static OpenTK.NMatrix4 CreateTranslation(SCNVector3 vector) { return(new OpenTK.NMatrix4(new OpenTK.Vector4(1, 0, 0, vector.X), new OpenTK.Vector4(0, 1, 0, vector.Y), new OpenTK.Vector4(0, 0, 1, vector.Z), new OpenTK.Vector4(0, 0, 0, 1))); }
public override void TouchesBegan(NSSet touches, UIEvent evt) { var forcePower = 10; base.TouchesBegan(touches, evt); var pointOfView = this.SceneView.PointOfView; var transform = pointOfView.Transform; var location = new SCNVector3(transform.M41, transform.M42, transform.M43); var orientation = new SCNVector3(-transform.M31, -transform.M32, -transform.M33); var position = location + orientation; var pokeball = new SCNNode() { Geometry = SCNSphere.Create(0.15f), }; pokeball.Geometry.FirstMaterial.Diffuse.ContentImage = UIImage.FromBundle("pokeball"); pokeball.Position = position; pokeball.PhysicsBody = SCNPhysicsBody.CreateDynamicBody(); pokeball.PhysicsBody.PhysicsShape = SCNPhysicsShape.Create(pokeball); pokeball.PhysicsBody.ContactTestBitMask = (int)BitMaskCategory.Pokemon; pokeball.PhysicsBody.CategoryBitMask = (int)BitMaskCategory.Pokeball; pokeball.PhysicsBody.ApplyForce(new SCNVector3(orientation.X * forcePower, orientation.Y * forcePower, orientation.Z * forcePower), true); SceneView.Scene.RootNode.AddChildNode(pokeball); }
public void BounceStuff(float multiplier) { if (i++ % 4 != 0) { return; } foreach (var node in Faces) { foreach (var i in Enumerable.Range(0, 1)) { var box = GetBox(); box.Position = new SCNVector3(0, .15f, 0); var vec = new SCNVector3(((float)r.NextDouble() - .5f) * multiplier, ((float)r.NextDouble() + (float)2) * multiplier, 0); box.PhysicsBody.ApplyForce(vec, true); node.Add(box); var newPosition = node.ConvertPositionToNode(box.Position, SCNView.Scene.RootNode); SCNView.Scene.RootNode.Add(box); box.Position = newPosition; } } }
private SCNNode GenerateEarth(SCNVector3 position) { var earth = SCNSphere.Create(EartRadious); eartParentNode = new SCNNode { Position = position, Geometry = earth }; earthNode = new SCNNode { Position = new SCNVector3(distanceEart, 0, 0), Geometry = earth }; earthNode.Geometry.FirstMaterial.Diffuse.ContentImage = UIImage.FromBundle("EartDifuse"); earthNode.Geometry.FirstMaterial.Specular.ContentImage = UIImage.FromBundle("EarthSpecular"); earthNode.Geometry.FirstMaterial.Emission.ContentImage = UIImage.FromBundle("EarthEmision"); earthNode.Geometry.FirstMaterial.Normal.ContentImage = UIImage.FromBundle("EarthNormal"); earthNode.Name = "Eart"; var moon = SCNSphere.Create(radiousMoon); moonNode = new SCNNode { Position = new SCNVector3(distanceMoon, 0, 0), Geometry = moon }; moonNode.Geometry.FirstMaterial.Diffuse.ContentImage = UIImage.FromBundle("moon_back"); moonNode.Name = "Moon"; eartParentNode.AddChildNode(moonNode); earthNode.AddChildNode(moonNode); eartParentNode.AddChildNode(earthNode); return(eartParentNode); }
void TapAction(UITapGestureRecognizer tap) { if (tap.State == UIGestureRecognizerState.Ended) { var tapLocation = tap.LocationInView(sceneView); var hitResults = sceneView.HitTest(tapLocation, new NSDictionary()); if (hitResults.Length != 0) { var NodeResult = hitResults[0].Node; if (NodeResult != null) { var nodeText = SCNText.Create(NodeResult.Name, 5); var textNode = SCNNode.Create(); textNode.Geometry = nodeText; textNode.Scale = new SCNVector3(0.01f, 0.01f, 0.01f); var min = new SCNVector3(); var max = new SCNVector3(); textNode.GetBoundingBox(ref min, ref max); textNode.Position = new SCNVector3((textNode.Position.X - (textNode.Scale.X / 2)), textNode.Position.Y + 0.5f, textNode.Position.Z); NodeResult.AddChildNode(textNode); } } } }
internal DetectedBoundingBox(NVector3[] points, double scale, UIColor color = null) : base() { // Cannot use asset-group defined color as default in args (since not compile-time constant), // so assign it now if default if (color == null) { color = Utilities.AppYellow; } var localMin = new SCNVector3(float.MaxValue, float.MaxValue, float.MaxValue); var localMax = new SCNVector3(float.MinValue, float.MinValue, float.MinValue); foreach (var point in points) { var scnVector = point.ToSCNVector3(); localMin = localMin.Min(scnVector); localMax = localMax.Max(scnVector); } Position = Position + (localMax + localMin) / 2; var extent = localMax - localMin; var wireframe = new Wireframe(extent.ToNVector3(), color, scale); AddChildNode(wireframe); }
/// <summary> /// Translates the location by comparing with a given position. /// </summary> /// <returns>The location.</returns> /// <param name="self">Self.</param> /// <param name="to">To.</param> public static CLLocation TranslatedLocation(this SceneLocationEstimate self, SCNVector3 to) { var translation = self.LocationTranslation(to); var translatedLocation = self.Location.TranslatedLocation(translation); return(translatedLocation); }
private void PresentPrimitives(PresentationViewController presentationViewController) { var count = 100; var spread = 0.0f; // create a cube with a sphere shape for (int i = 0; i < count; ++i) { var model = SCNNode.Create(); model.Position = GroundNode.ConvertPositionToNode(new SCNVector3(RandFloat(-1, 1), RandFloat(30, 50), RandFloat(-1, 1)), null); model.EulerAngles = new SCNVector3(RandFloat(0, (nfloat)Math.PI * 2), RandFloat(0, (nfloat)Math.PI * 2), RandFloat(0, (nfloat)Math.PI * 2)); var size = new SCNVector3(RandFloat(1.0, 1.5), RandFloat(1.0, 1.5), RandFloat(1.0, 1.5)); var random = new Random((int)DateTime.Now.Ticks); int geometryIndex = random.Next(0, 7); switch (geometryIndex) { case 0: // Box model.Geometry = SCNBox.Create(size.X, size.Y, size.Z, 0); break; case 1: // Pyramid model.Geometry = SCNPyramid.Create(size.X, size.Y, size.Z); break; case 2: // Sphere model.Geometry = SCNSphere.Create(size.X); break; case 3: // Cylinder model.Geometry = SCNCylinder.Create(size.X, size.Y); break; case 4: // Tube model.Geometry = SCNTube.Create(size.X, size.X + size.Z, size.Y); break; case 5: // Capsule model.Geometry = SCNCapsule.Create(size.X, size.Y + 2 * size.X); break; case 6: // Torus model.Geometry = SCNTorus.Create(size.X, (nfloat)Math.Min(size.X, size.Y) / 2); break; default: break; } model.Geometry.FirstMaterial.Multiply.Contents = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/texture", "png")); model.PhysicsBody = SCNPhysicsBody.CreateDynamicBody(); model.PhysicsBody.Velocity = new SCNVector3(RandFloat(-spread, spread), -10, RandFloat(-spread, spread)); model.PhysicsBody.AngularVelocity = new SCNVector4(RandFloat(-1, 1), RandFloat(-1, 1), RandFloat(-1, 1), RandFloat(-3, 3)); Shapes.Add(model); ((SCNView)presentationViewController.View).Scene.RootNode.AddChildNode(model); } }
public static SCNMatrix4 SetPosition (this SCNMatrix4 matrix, SCNVector3 vector) { matrix.M41 = vector.X; matrix.M42 = vector.Y; matrix.M43 = vector.Z; return matrix; }
public void SetGrabMode(bool state) { this.physicsMode = !state; // physics mode is off when grab mode is on if (this.physicsMode) { this.currentPosition = catapult.Position; } }
public SlingshotComponent(SCNNode catapult) : base() { this.catapult = catapult; this.restPosition = catapult.Position; this.currentPosition = this.restPosition; this.physicsMode = false; // Started off and gets turned on only if needed this.velocity = SCNVector3.Zero; }
/// <summary> /// Returns the interpolated tangent at a given length (l from 0.0 to totalLength) /// </summary> public SCNVector3 Tangent(float l) { var s = this.FindIndex(l); return(SCNVector3.Normalize(SimdExtensions.Mix(this.Tangents[this.lastIndex], this.Tangents[this.lastIndex + 1], new SCNVector3(s, s, s)))); }
public override void MagnifyWithEvent(NSEvent theEvent) { base.MagnifyWithEvent(theEvent); var magnification = theEvent.Magnification; var zoom = new SCNVector3(magnification, magnification, magnification); Trackball.Zoom(zoom); }
public static SCNMatrix4 SetPosition(this SCNMatrix4 matrix, SCNVector3 vector) { matrix.M41 = vector.X; matrix.M42 = vector.Y; matrix.M43 = vector.Z; return(matrix); }
public static void Normalize(this SCNVector3 vector3) { var normalizedVector = vector3.Normalized(); vector3.X = normalizedVector.X; vector3.Y = normalizedVector.Y; vector3.Z = normalizedVector.Z; }
SCNVector3 MakeThrowPosition(SCNMatrix4 transform) { var force = new Vector3(0.0f, 0.0f, -0.3f); var rotation = new SCNVector3(transform.M31, transform.M32, transform.M33); var rotatedForce = SCNVector3.Multiply(rotation, force) + new Vector3(0.0f, 0.1f, 0.0f); return(new SCNVector3(rotatedForce)); }
public static unsafe SCNGeometrySource FromVertices(SCNVector3 [] vertices) { if (vertices == null) throw new ArgumentNullException ("vertices"); fixed (SCNVector3 *ptr = &vertices [0]) return FromVertices ((IntPtr)ptr, vertices.Length); }
public FeatureHitTestResult(SCNVector3 position, float distanceToRayOrigin, SCNVector3 featureHit, float featureDistanceToHitResult) { // Initialize Position = position; DistanceToRayOrigin = distanceToRayOrigin; FeatureHit = featureHit; FeatureDistanceToHitResult = featureDistanceToHitResult; }
public static unsafe SCNGeometrySource FromNormals(SCNVector3 [] normals) { if (normals == null) throw new ArgumentNullException ("normals"); fixed (SCNVector3 *ptr = &normals[0]) return FromNormals ((IntPtr)ptr, normals.Length); }
internal Ray(SCNNode pointOfView, float length) { pointOfView.WorldFront.NormalizeFast(); var cameraNormal = pointOfView.WorldFront.Times(length); Origin = pointOfView.WorldPosition; Direction = cameraNormal.ToSCNVector3(); }
public void Update(ARPlaneAnchor planeAnchor) { planeGeometry.Width = planeAnchor.Extent.X; planeGeometry.Length = planeAnchor.Extent.Z; Position = new SCNVector3( planeAnchor.Center.X, planeAnchor.Center.Y, planeAnchor.Center.Z); }
public static SCNVector3 Reduce(this IList <SCNVector3> items, SCNVector3 initialResult) { foreach (var item in items) { initialResult += item; } return(initialResult); }
public GamePhysicsSmoothComponent(SCNNode physicsNode, SCNNode geometryNode) : base() { this.physicsNode = physicsNode; this.geometryNode = geometryNode; // get initial offset this.parentOffPos = this.geometryNode.Position; this.parentOffRot = this.geometryNode.Orientation; }
public void Update(double deltaTime, SCNSceneRenderer aRenderer) { // Based on gamestate: // ingame: Move the character if running. // ingame: prevent movement of the character past our level bounds. // ingame: perform logic for the player character. // any: move the directional light with any player movement. // ingame: update the coconuts kinematically. // ingame: perform logic for each monkey. // ingame: because our camera could have moved, update the transforms needs to fly // collected bananas from the player (world space) to score (screen space) var appDelegate = SharedAppDelegate.AppDelegate; var currentState = GameSimulation.Sim.CurrentGameState; // Move character along path if walking. MoveCharacterAlongPathWith(deltaTime, currentState); // Based on the time along path, rotation the character to face the correct direction. PlayerCharacter.Rotation = GetPlayerDirectionFromCurrentPosition(); if (currentState == GameState.InGame) { PlayerCharacter.Update(deltaTime); } // Move the light UpdateSunLightPosition(); if (currentState == GameState.PreGame || currentState == GameState.PostGame || currentState == GameState.Paused) { return; } foreach (MonkeyCharacter monkey in Monkeys) { monkey.Update(deltaTime); } // Update timer and check for Game Over. SecondsRemaining -= deltaTime; if (SecondsRemaining < 0.0) { DoGameOver(); } // update the player's SP position. SCNVector3 playerPosition = PlayerCharacter.WorldTransform.GetPosition(); screenSpacePlayerPosition = appDelegate.Scene.ProjectPoint(playerPosition); // Update the SP position of the score label CGPoint pt = ScoreLabelLocation; worldSpaceLabelScorePosition = appDelegate.Scene.UnprojectPoint(new SCNVector3(pt.X, pt.Y, screenSpacePlayerPosition.Z)); }
public void DidCollision(SCNNode nodeA, SCNNode nodeB, SCNVector3 position, float impulse) { foreach (var interaction in this.interactions.Values) { // nodeA and nodeB take turn to be the main node interaction.DidCollision(nodeA, nodeB, position, impulse); interaction.DidCollision(nodeB, nodeA, position, impulse); } }
public static SCNQuaternion CreateQuaternion(SCNVector3 v1, SCNVector3 v2) { var a = SCNVector3.Cross(v1, v2); var w = (float)Math.Sqrt(v1.LengthSquared * v2.LengthSquared) + SCNVector3.Dot(v1, v2); var result = new SCNQuaternion(a.X, a.Y, a.Z, w); result.Normalize(); return(result); }
private static SCNVector3 Cross(SCNVector3 a, SCNVector3 b) { SCNVector3 c; c.X = a.Y * b.Z - a.Z * b.Y; c.Y = a.Z * b.X - a.X * b.Z; c.Z = a.X * b.Y - a.Y * b.X; return(c); }
private SCNNode CreatePoolBall(SCNVector3 position) { var model = SCNNode.Create(); model.Position = position; model.Geometry = SCNSphere.Create(0.7f); model.Geometry.FirstMaterial.Diffuse.Contents = new NSImage(NSBundle.MainBundle.PathForResource("Scenes.scnassets/pool/pool_8", "png")); model.PhysicsBody = SCNPhysicsBody.CreateDynamicBody(); return(model); }
private void ApplyRandomTorque(SCNPhysicsBody physicsBody, float maxTorque) { var randomAxis = new SCNVector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); randomAxis = SCNVector3.Normalize(randomAxis); var randomTorque = new SCNVector4(randomAxis, (float)(random.NextDouble() * 2d - 1d) * maxTorque); physicsBody.ApplyTorque(randomTorque, true); }
public PlaneNode(float width, float length, SCNVector3 position, SKScene videoScene) { var rootNode = new SCNNode { Geometry = CreateGeometry(width, length, videoScene), Position = position }; AddChildNode(rootNode); }
public static SCNPhysicsShape Create(SCNGeometry geometry, SCNPhysicsShapeType? shapeType = null, bool? keepAsCompound = null, SCNVector3? scale = null) { return Create (geometry, new SCNPhysicsShapeOptions { ShapeType = shapeType, KeepAsCompound = keepAsCompound, Scale = scale }.ToDictionary ()); }
public static SCNVector3 GetMinVector (SCNVector3 vectorLeft, SCNVector3 vectorRight) { SCNVector3 min = vectorLeft; if (vectorRight.X < vectorLeft.X) min.X = vectorRight.X; if (vectorRight.Y < vectorLeft.Y) min.Y = vectorRight.Y; if (vectorRight.Z < vectorLeft.Z) min.Z = vectorRight.Z; return min; }
public static SCNVector3 GetMaxVector (SCNVector3 vectorLeft, SCNVector3 vectorRight) { SCNVector3 max = vectorLeft; if (vectorRight.X > vectorLeft.X) max.X = vectorRight.X; if (vectorRight.Y > vectorLeft.Y) max.Y = vectorRight.Y; if (vectorRight.Z > vectorLeft.Z) max.Z = vectorRight.Z; return max; }
public static SCNPhysicsShape Create(SCNPhysicsShape [] shapes, SCNVector3 [] transforms) { if (shapes == null) throw new ArgumentNullException ("shapes"); if (transforms == null) throw new ArgumentNullException ("transforms"); var t = new NSValue [transforms.Length]; for (var i = 0; i < t.Length; i++) t [i] = NSValue.FromVector (transforms [i]); return Create (shapes, t); }
public static SCNNode SCAddChildNode (SCNNode container, string name, string path, nfloat scale) { // Load the scene from the specified file var scene = SCNScene.FromFile (path); // Retrieve the root node var node = scene.RootNode; // Search for the node named "name" if (name.Length > 0) node = node.FindChildNode (name, true); else node = node.ChildNodes [0]; // Take the first child if no name is passed if (scale != 0) { // Rescale based on the current bounding box and the desired scale // Align the node to 0 on the Y axis var min = new SCNVector3 (); var max = new SCNVector3 (); node.GetBoundingBox (ref min, ref max); var mid = SCNVector3.Add (min, max); mid = SCNVector3.Multiply (mid, 0.5f); mid.Y = min.Y; // Align on bottom var size = SCNVector3.Subtract (max, min); var maxSize = NMath.Max (NMath.Max (size.X, size.Y), size.Z); scale = scale / maxSize; mid = SCNVector3.Multiply (mid, scale); mid = -mid; node.Scale = new SCNVector3 (scale, scale, scale); node.Position = new SCNVector3 (mid); } // Add to the container passed in argument container.AddChildNode (node); return node; }
public override void PresentStep (int index, PresentationViewController presentationViewController) { Step = index; switch (index) { case 0: break; case 1: TextManager.FlipOutText (SlideTextManager.TextType.Bullet); TextManager.SetSubtitle ("SCNPhysicsBody"); TextManager.FlipInText (SlideTextManager.TextType.Subtitle); TextManager.AddBulletAtLevel ("Dynamic Bodies", 0); // Add some code TextManager.AddCode ("#// Make a node dynamic\n" + "aNode.#physicsBody# = [SCNPhysicsBody #dynamicBody#];#"); TextManager.FlipInText (SlideTextManager.TextType.Bullet); TextManager.FlipInText (SlideTextManager.TextType.Code); break; case 2: //add a cube var worldPos = GroundNode.ConvertPositionToNode (new SCNVector3 (0, 12, 2), null); var dice = CreateBlock (worldPos, new SCNVector3 (1.5f, 1.5f, 1.5f)); dice.PhysicsBody = null; //wait! dice.Rotation = new SCNVector4 (0, 0, 1, (float)(Math.PI / 4) * 0.5f); dice.Scale = new SCNVector3 (0.001f, 0.001f, 0.001f); ((SCNView)presentationViewController.View).Scene.RootNode.AddChildNode (dice); SCNTransaction.Begin (); SCNTransaction.AnimationDuration = 0.75f; dice.Scale = new SCNVector3 (2, 2, 2); SCNTransaction.Commit (); Dices.Add (dice); break; case 3: foreach (var node in Dices) node.PhysicsBody = SCNPhysicsBody.CreateDynamicBody (); break; case 4: PresentDices (presentationViewController); break; case 5: TextManager.FlipOutText (SlideTextManager.TextType.Bullet); TextManager.FlipOutText (SlideTextManager.TextType.Code); TextManager.AddBulletAtLevel ("Manipulate with forces", 0); // Add some code TextManager.AddCode ("#// Apply an impulse\n" + "[aNode.physicsBody #applyForce:#aVector3 #atPosition:#aVector3 #impulse:#YES];#"); TextManager.FlipInText (SlideTextManager.TextType.Bullet); TextManager.FlipInText (SlideTextManager.TextType.Code); break; case 6: // remove dices var center = new SCNVector3 (0, -5, 20); center = GroundNode.ConvertPositionToNode (center, null); Explosion (center, Dices); var popTime = new DispatchTime (DispatchTime.Now, (long)(1 * Utils.NSEC_PER_SEC)); DispatchQueue.MainQueue.DispatchAfter (popTime, () => { TextManager.FlipOutText (SlideTextManager.TextType.Code); TextManager.FlipOutText (SlideTextManager.TextType.Bullet); TextManager.AddBulletAtLevel ("Static Bodies", 0); TextManager.AddCode ("#// Make a node static\n" + "aNode.#physicsBody# = [SCNPhysicsBody #staticBody#];#"); TextManager.FlipInText (SlideTextManager.TextType.Bullet); TextManager.FlipInText (SlideTextManager.TextType.Code); }); break; case 7: PresentWalls (presentationViewController); break; case 8: PresentBalls (presentationViewController); break; case 9: //remove walls var walls = new List<SCNNode> (); GroundNode.EnumerateChildNodes (delegate(SCNNode node, out bool stop) { stop = false; if (node.Name == "container-wall") { node.RunAction (SCNAction.Sequence (new SCNAction [] { SCNAction.MoveBy (new SCNVector3 (0, -2, 0), 0.5), SCNAction.RemoveFromParentNode () })); walls.Add (node); } return stop; }); break; case 10: // remove balls center = new SCNVector3 (0, -5, 5); center = GroundNode.ConvertPositionToNode (center, null); Explosion (center, Balls); popTime = new DispatchTime (DispatchTime.Now, (long)(0.5 * Utils.NSEC_PER_SEC)); DispatchQueue.MainQueue.DispatchAfter (popTime, () => { TextManager.FlipOutText (SlideTextManager.TextType.Code); TextManager.FlipOutText (SlideTextManager.TextType.Bullet); TextManager.AddBulletAtLevel ("Kinematic Bodies", 0); TextManager.AddCode ("#// Make a node kinematic\n" + "aNode.#physicsBody# = [SCNPhysicsBody #kinematicBody#];#"); TextManager.FlipInText (SlideTextManager.TextType.Bullet); TextManager.FlipInText (SlideTextManager.TextType.Code); }); break; case 11: var boxNode = SCNNode.Create (); boxNode.Geometry = SCNBox.Create (10, 0.2f, 10, 0); boxNode.Position = new SCNVector3 (0, 5, MIDDLE_Z); boxNode.Geometry.FirstMaterial.Emission.Contents = NSColor.DarkGray; boxNode.PhysicsBody = SCNPhysicsBody.CreateKinematicBody (); boxNode.RunAction (SCNAction.RepeatActionForever (SCNAction.RotateBy (0, 0, NMath.PI * 2, 2.0))); GroundNode.AddChildNode (boxNode); KinematicItems.Add (boxNode); var invisibleWall = SCNNode.Create (); invisibleWall.Geometry = SCNBox.Create (4, 40, 10, 0); invisibleWall.Position = new SCNVector3 (-7, 0, MIDDLE_Z); invisibleWall.Geometry.FirstMaterial.Transparency = 0; invisibleWall.PhysicsBody = SCNPhysicsBody.CreateStaticBody (); GroundNode.AddChildNode (invisibleWall); KinematicItems.Add (invisibleWall); invisibleWall = (SCNNode)invisibleWall.Copy (); invisibleWall.Position = new SCNVector3 (7, 0, MIDDLE_Z); GroundNode.AddChildNode (invisibleWall); KinematicItems.Add (invisibleWall); invisibleWall = (SCNNode)invisibleWall.Copy (); invisibleWall.Geometry = SCNBox.Create (10, 40, 4, 0); invisibleWall.Geometry.FirstMaterial.Transparency = 0; invisibleWall.Position = new SCNVector3 (0, 0, MIDDLE_Z - 7); invisibleWall.PhysicsBody = SCNPhysicsBody.CreateStaticBody (); GroundNode.AddChildNode (invisibleWall); KinematicItems.Add (invisibleWall); invisibleWall = (SCNNode)invisibleWall.Copy (); invisibleWall.Position = new SCNVector3 (0, 0, MIDDLE_Z + 7); GroundNode.AddChildNode (invisibleWall); KinematicItems.Add (invisibleWall); for (int i = 0; i < 100; i++) { var ball = SCNNode.Create (); worldPos = boxNode.ConvertPositionToNode (new SCNVector3 (RandFloat (-4, 4), RandFloat (10, 30), RandFloat (-1, 4)), null); ball.Position = worldPos; ball.Geometry = SCNSphere.Create (0.5f); ball.Geometry.FirstMaterial.Diffuse.Contents = NSColor.Cyan; ball.PhysicsBody = SCNPhysicsBody.CreateDynamicBody (); ((SCNView)presentationViewController.View).Scene.RootNode.AddChildNode (ball); KinematicItems.Add (ball); } break; case 12: TextManager.FlipOutText (SlideTextManager.TextType.Code); TextManager.FlipOutText (SlideTextManager.TextType.Bullet); TextManager.FlipOutText (SlideTextManager.TextType.Subtitle); TextManager.SetSubtitle ("SCNPhysicsShape"); TextManager.AddCode ("#// Configure the physics shape\n\n" + "aNode.physicsBody.#physicsShape# = \n\t[#SCNPhysicsShape# shapeWithGeometry:aGeometry options:options];#"); TextManager.FlipInText (SlideTextManager.TextType.Bullet); TextManager.FlipInText (SlideTextManager.TextType.Code); KinematicItems[0].RunAction (SCNAction.Sequence (new SCNAction[] { SCNAction.FadeOut (0.5), SCNAction.RemoveFromParentNode () })); for (int i = 1; i < 5; i++) KinematicItems[i].RemoveFromParentNode (); KinematicItems = null; break; case 13: //add meshes PresentMeshes (presentationViewController); break; case 14: // remove meshes center = new SCNVector3 (0, -5, 20); center = GroundNode.ConvertPositionToNode (center, null); Explosion (center, Meshes); break; case 15: // add shapes PresentPrimitives (presentationViewController); break; case 16: // remove shapes center = new SCNVector3 (0, -5, 20); center = GroundNode.ConvertPositionToNode (center, null); Explosion (center, Shapes); popTime = new DispatchTime (DispatchTime.Now, (long)(0.5 * Utils.NSEC_PER_SEC)); DispatchQueue.MainQueue.DispatchAfter (popTime, () => { TextManager.FlipOutText (SlideTextManager.TextType.Code); TextManager.FlipOutText (SlideTextManager.TextType.Bullet); TextManager.FlipOutText (SlideTextManager.TextType.Subtitle); TextManager.SetSubtitle ("SCNPhysicsBehavior"); TextManager.AddCode ("#// setup a physics behavior\n\n" + "#SCNPhysicsHingeJoint# *joint = [SCNPhysicsHingeJoint\n\n" + "jointWithBodyA:#nodeA.physicsBody# axisA:[...] anchorA:[...]\n\n" + "bodyB:#nodeB.physicsBody# axisB:[...] anchorB:[...]];\n\n\n" + "[scene.#physicsWorld# addBehavior:joint];#"); TextManager.FlipInText (SlideTextManager.TextType.Bullet); TextManager.FlipInText (SlideTextManager.TextType.Subtitle); TextManager.FlipInText (SlideTextManager.TextType.Code); }); break; case 17: //add meshes PresentHinge (presentationViewController); break; case 18: //remove constraints ((SCNView)presentationViewController.View).Scene.PhysicsWorld.RemoveAllBehaviors (); foreach (var node in Hinges) node.RunAction (SCNAction.Sequence (new SCNAction[] { SCNAction.Wait (3.0), SCNAction.FadeOut (0.5), SCNAction.RemoveFromParentNode () })); break; case 19: TextManager.FlipOutText (SlideTextManager.TextType.Bullet); TextManager.FlipOutText (SlideTextManager.TextType.Subtitle); TextManager.FlipOutText (SlideTextManager.TextType.Code); TextManager.SetSubtitle ("More..."); TextManager.FlipInText (SlideTextManager.TextType.Subtitle); TextManager.AddBulletAtLevel ("SCNPhysicsField", 0); TextManager.AddBulletAtLevel ("SCNPhysicsVehicle", 0); TextManager.FlipInText (SlideTextManager.TextType.Bullet); TextManager.FlipInText (SlideTextManager.TextType.Code); break; } }
public virtual void Update (ISCNSceneRenderer renderer, double timeInSeconds) { // delta time since last update if (Math.Abs (previousUpdateTime) < float.Epsilon) previousUpdateTime = timeInSeconds; double deltaTime = Math.Min (Math.Max (1.0 / 60.0, timeInSeconds - previousUpdateTime), 1f); previousUpdateTime = timeInSeconds; // Reset some states every frame maxPenetrationDistance = 0; positionNeedsAdjustment = false; SCNVector3 direction = GameView.CurrentDirection; SCNVector3 initialPosition = Character.Node.Position; // Move if (Math.Abs (direction.X) > float.Epsilon && Math.Abs (direction.Z) > float.Epsilon) { var characterSpeed = (float)deltaTime * CharacterSpeedFactor * .84f; Character.Node.Position = new SCNVector3 ( initialPosition.X + direction.X * characterSpeed, initialPosition.Y + direction.Y * characterSpeed, initialPosition.Z + direction.Z * characterSpeed ); // update orientation double angle = Math.Atan2 (direction.X, direction.Z); Character.Direction = (float)angle; Character.Walking = true; } else { Character.Walking = false; } var p0 = Character.Node.Position; var p1 = Character.Node.Position; p0.Y -= MaxJump; p1.Y += MaxRise; var options = new SCNPhysicsTest { CollisionBitMask = (nuint)(int)(Bitmask.Collision | Bitmask.Water), SearchMode = SCNPhysicsSearchMode.Closest }; SCNHitTestResult[] results = GameView.Scene.PhysicsWorld.RayTestWithSegmentFromPoint (p1, p0, options); float groundY = -10; if (results.Length > 0) { SCNHitTestResult result = results [0]; groundY = result.WorldCoordinates.Y; UpdateCameraWithCurrentGround (result.Node); SCNMaterial groundMaterial = result.Node.ChildNodes [0].Geometry.FirstMaterial; if (grassArea == groundMaterial) { Character.CurrentFloorMaterial = FloorMaterial.Grass; } else if (waterArea == groundMaterial) { if (Character.Burning) { Character.Pshhhh (); Character.Node.RunAction (SCNAction.Sequence (new [] { SCNAction.PlayAudioSource (pshhhSound, true), SCNAction.PlayAudioSource (aahSound, false) })); } Character.CurrentFloorMaterial = FloorMaterial.Water; options = new SCNPhysicsTest { CollisionBitMask = (nuint)(int)Bitmask.Collision, SearchMode = SCNPhysicsSearchMode.Closest }; results = GameView.Scene.PhysicsWorld.RayTestWithSegmentFromPoint (p1, p0, options); result = results [0]; groundY = result.WorldCoordinates.Y; } else { Character.CurrentFloorMaterial = FloorMaterial.Rock; } } // var nextPosition = Character.Node.Position; // const double threshold = 1e-5; // // if (groundY < nextPosition.Y - threshold) { // // approximation of acceleration for a delta time // accelerationY += (float)(deltaTime * GravityAcceleration); // if (groundY < nextPosition.Y - 0.2) // Character.CurrentFloorMaterial = FloorMaterial.Air; // } else { // accelerationY = 0; // } // // nextPosition.Y -= accelerationY; // // // reset acceleration if we touch the ground // if (groundY > nextPosition.Y) { // accelerationY = 0; // nextPosition.Y = groundY; // } // Flames are static physics bodies, but they are moved by an action - So we need to tell the physics engine that the transforms did change. foreach (SCNNode flame in flames) flame.PhysicsBody.ResetTransform (); // Adjust the volume of the enemy based on the distance with the character. float distanceToClosestEnemy = float.MaxValue; SCNVector3 pos3 = Character.Node.Position; foreach (SCNNode enemy in enemies) { // distance to enemy SCNMatrix4 enemyMat = enemy.WorldTransform; var enemyPosition = new SCNVector3 (enemyMat.M41, enemyMat.M42, enemyMat.M43); float distance = SCNVector3.Subtract (pos3, enemyPosition).Length; distanceToClosestEnemy = Math.Min (distanceToClosestEnemy, distance); } // Adjust sounds volumes based on distance with the enemy. if (!gameIsComplete) { double fireVolume = 0.3 * Math.Max (0.0, Math.Min (1.0, 1.0 - (distanceToClosestEnemy - 1.2) / 1.6)); var mixerNode = flameThrowerSound.AudioNode as AVAudioMixerNode; if (mixerNode != null) mixerNode.Volume = (float)fireVolume; } }
void UpdateCameraWithCurrentGround (SCNNode node) { if (gameIsComplete) return; if (currentGround == null) { currentGround = node; return; } if (node != null && node != currentGround) { currentGround = node; if (groundToCameraPosition.ContainsKey (node)) { var position = groundToCameraPosition [node]; if (node == mainGround && Character.Node.Position.X < 2.5) position = new SCNVector3 (-0.098175f, 3.926991f, 0f); SCNAction actionY = SCNAction.RotateTo (0f, position.Y, 0f, 3.0, true); actionY.TimingMode = SCNActionTimingMode.EaseInEaseOut; SCNAction actionX = SCNAction.RotateTo (position.X, 0f, 0f, 3.0, true); actionX.TimingMode = SCNActionTimingMode.EaseInEaseOut; cameraXHandle.RunAction (actionY); cameraXHandle.RunAction (actionX); } } }
public PlayerCharacter (SCNNode characterNode) : base (characterNode) { CategoryBitMask = NodeCategory.Lava; velocity = SCNVector3.Zero; IsWalking = false; changingDirection = false; baseWalkSpeed = 0.0167f; JumpBoost = 0.0f; WalkSpeed = baseWalkSpeed * 2; Jumping = false; groundPlaneHeight = 0.0f; playerWalkDirection = WalkDirection.Right; cameraHelper = new SCNNode { Position = new SCNVector3 (1000f, 200f, 0f) }; AddChildNode (cameraHelper); CollideSphere = new SCNNode { Position = new SCNVector3 (0f, 80f, 0f) }; SCNGeometry geo = SCNCapsule.Create (90f, 160f); SCNPhysicsShape shape2 = SCNPhysicsShape.Create (geo, (NSDictionary)null); CollideSphere.PhysicsBody = SCNPhysicsBody.CreateBody (SCNPhysicsBodyType.Kinematic, shape2); CollideSphere.PhysicsBody.CollisionBitMask = GameCollisionCategory.Banana | GameCollisionCategory.Coin | GameCollisionCategory.Coconut | GameCollisionCategory.Lava; CollideSphere.PhysicsBody.CategoryBitMask = GameCollisionCategory.Player; AddChildNode (CollideSphere); DustPoof = GameSimulation.LoadParticleSystemWithName ("dust"); NSString artResourcePath = (NSString)GameSimulation.PathForArtResource ("level/effects/effects_transparent.png"); DustPoof.ParticleImage = artResourcePath; DustWalking = GameSimulation.LoadParticleSystemWithName ("dustWalking"); DustWalking.ParticleImage = artResourcePath; dustWalkingBirthRate = DustWalking.BirthRate; // Load the animations and store via a lookup table. SetupIdleAnimation (); SetupRunAnimation (); SetupJumpAnimation (); SetupBoredAnimation (); SetupHitAnimation (); PlayIdle (); }
SCNVector4 GetDirectionFromPosition (SCNVector3 currentPosition) { SCNVector3 target = LocationAlongPath (TimeAlongPath - 0.05f); SCNMatrix4 lookAt = SCNMatrix4.LookAt (currentPosition, target, new SCNVector3 (0f, 1f, 0f)); SCNQuaternion q = lookAt.ToQuaternion (); nfloat angle = 0; q.ToAxisAngle (out target, out angle); if (PlayerCharacter.PlayerWalkDirection == WalkDirection.Left) angle -= (nfloat)Math.PI; return new SCNVector4 (0f, 1f, 0f, angle); }
public void Update (double deltaTime, SCNSceneRenderer aRenderer) { // Based on gamestate: // ingame: Move the character if running. // ingame: prevent movement of the character past our level bounds. // ingame: perform logic for the player character. // any: move the directional light with any player movement. // ingame: update the coconuts kinematically. // ingame: perform logic for each monkey. // ingame: because our camera could have moved, update the transforms needs to fly // collected bananas from the player (world space) to score (screen space) var appDelegate = SharedAppDelegate.AppDelegate; var currentState = GameSimulation.Sim.CurrentGameState; // Move character along path if walking. MoveCharacterAlongPathWith (deltaTime, currentState); // Based on the time along path, rotation the character to face the correct direction. PlayerCharacter.Rotation = GetPlayerDirectionFromCurrentPosition (); if (currentState == GameState.InGame) PlayerCharacter.Update (deltaTime); // Move the light UpdateSunLightPosition (); if (currentState == GameState.PreGame || currentState == GameState.PostGame || currentState == GameState.Paused) return; foreach (MonkeyCharacter monkey in Monkeys) monkey.Update (deltaTime); // Update timer and check for Game Over. SecondsRemaining -= deltaTime; if (SecondsRemaining < 0.0) DoGameOver (); // update the player's SP position. SCNVector3 playerPosition = PlayerCharacter.WorldTransform.GetPosition (); screenSpacePlayerPosition = appDelegate.Scene.ProjectPoint (playerPosition); // Update the SP position of the score label CGPoint pt = ScoreLabelLocation; worldSpaceLabelScorePosition = appDelegate.Scene.UnprojectPoint (new SCNVector3 (pt.X, pt.Y, screenSpacePlayerPosition.Z)); }
public void CollectBanana (SCNNode banana) { // Flyoff the banana to the screen space position score label. // Don't increment score until the banana hits the score label. // ignore collisions banana.PhysicsBody = null; BananasCollected++; int variance = 60; nfloat duration = 0.25f; nfloat apexY = worldSpaceLabelScorePosition.Y * 0.8f + (new Random ().Next (0, variance) - variance / 2); worldSpaceLabelScorePosition.Z = banana.Position.Z; var apex = new SCNVector3 (banana.Position.X + 10 + (new Random ().Next (0, variance) - variance / 2), apexY, banana.Position.Z); SCNAction startFlyOff = SCNAction.MoveTo (apex, duration); startFlyOff.TimingMode = SCNActionTimingMode.EaseOut; SCNAction endFlyOff = SCNAction.CustomAction (duration, new SCNActionNodeWithElapsedTimeHandler ((node, elapsedTime) => { nfloat t = elapsedTime / duration; var v = new SCNVector3 ( apex.X + ((worldSpaceLabelScorePosition.X - apex.X) * t), apex.Y + ((worldSpaceLabelScorePosition.Y - apex.Y) * t), apex.X + ((worldSpaceLabelScorePosition.Z - apex.Z) * t)); node.Position = v; })); endFlyOff.TimingMode = SCNActionTimingMode.EaseInEaseOut; SCNAction flyoffSequence = SCNAction.Sequence (new SCNAction[] { startFlyOff, endFlyOff }); banana.RunAction (flyoffSequence, () => { Bananas.Remove (banana); banana.RemoveFromParentNode (); // Add to score. Score++; GameSimulation.Sim.PlaySound ("deposit.caf"); // Game Over if (Bananas.Count == 0) DoGameOver (); }); }
// Takes a string an creates a node hierarchy where each letter is an independent geometry that is animated private SCNNode SplittedStylizedText (string message) { var textNode = SCNNode.Create (); var frontMaterial = TextFrontMaterial (); var border = TextSideAndChamferMaterial (); // Current x position of the next letter to add var positionX = 0.0f; // For each letter for (var i = 0; i < message.Length; i++) { var letterNode = SCNNode.Create (); var letterString = message.Substring (i, 1); var text = SCNText.Create (letterString, 50.0f); text.Font = NSFont.FromFontName ("Avenir Next Heavy", 288); text.ChamferRadius = 3.0f; text.ChamferProfile = TextChamferProfile (); // use a different material for the "heart" character var finalFrontMaterial = frontMaterial; if (i == 1) { finalFrontMaterial = (SCNMaterial)finalFrontMaterial.Copy (); finalFrontMaterial.Diffuse.Contents = NSColor.Red; finalFrontMaterial.Reflective.Contents = NSColor.Black; letterNode.Scale = new SCNVector3 (1.1f, 1.1f, 1.0f); } text.Materials = new SCNMaterial[] { finalFrontMaterial, finalFrontMaterial, border, border, border }; letterNode.Geometry = text; textNode.AddChildNode (letterNode); // measure the letter we just added to update the position SCNVector3 min, max; max = new SCNVector3 (0, 0, 0); min = new SCNVector3 (0, 0, 0); if (letterNode.GetBoundingBox (ref min, ref max)) { letterNode.Position = new SCNVector3 (positionX - min.X + (max.X + min.X) * 0.5f, -min.Y, 0); positionX += (float)max.X; } else { // if we have no bounding box, it is probably because of the "space" character. In that case, move to the right a little bit. positionX += 50.0f; } // Place the pivot at the center of the letter so that the rotation animation looks good letterNode.Pivot = SCNMatrix4.CreateTranslation ((max.X + min.X) * 0.5f, 0, 0); // Animate the letter var animation = CAKeyFrameAnimation.GetFromKeyPath ("rotation"); animation.Duration = 4.0f; animation.KeyTimes = new NSNumber[] { 0.0f, 0.3f, 1.0f }; animation.Values = new NSObject[] { NSValue.FromVector (new SCNVector4 (0, 1, 0, 0)), NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI * 2))), NSValue.FromVector (new SCNVector4 (0, 1, 0, (float)(Math.PI * 2))) }; var timingFunction = CAMediaTimingFunction.FromName (CAMediaTimingFunction.EaseInEaseOut); animation.TimingFunctions = new CAMediaTimingFunction[] { timingFunction, timingFunction, timingFunction }; animation.RepeatCount = float.MaxValue; animation.BeginTime = CAAnimation.CurrentMediaTime () + 1.0 + i * 0.2; // desynchronize animations letterNode.AddAnimation (animation, new NSString ("letterNodeAnimation")); } return textNode; }
private void AddWoodenBlockToScene (SCNScene scene, NSString imageName, SCNVector3 position) { var block = SCNNode.Create (); block.Position = position; block.Geometry = new SCNBox { Width = 5f, Height = 5f, Length = 5f, ChamferRadius = 0f }; block.Geometry.FirstMaterial.Diffuse.Contents = imageName; block.Geometry.FirstMaterial.Diffuse.MipFilter = SCNFilterMode.Linear; block.PhysicsBody = SCNPhysicsBody.CreateDynamicBody (); scene.RootNode.AddChildNode (block); }
private void AddTrainToScene (SCNScene scene, SCNVector3 position) { var max = SCNVector3.Zero; var min = SCNVector3.Zero; var trainScene = SCNScene.FromFile ("train_flat", ResourceManager.ResourceFolder, (NSDictionary)null); foreach (var node in trainScene.RootNode.ChildNodes) { if (node.Geometry != null) { node.Position = new SCNVector3 ( node.Position.X + position.X, node.Position.Y + position.Y, node.Position.Z + position.Z ); max = SCNVector3.Zero; min = SCNVector3.Zero; node.GetBoundingBox (ref min, ref max); var body = SCNPhysicsBody.CreateDynamicBody (); var boxShape = new SCNBox { Width = max.X - min.X, Height = max.Y - min.Y, Length = max.Z - min.Z, ChamferRadius = 0f }; body.PhysicsShape = SCNPhysicsShape.Create (boxShape, (NSDictionary)null); node.Pivot = SCNMatrix4.CreateTranslation (0f, -min.Y, 0f); node.PhysicsBody = body; scene.RootNode.AddChildNode (node); } } var smokeHandle = scene.RootNode.FindChildNode ("Smoke", true); var smokeParticleSystem = SCNParticleSystem.Create ("smoke", ResourceManager.ResourceFolder); smokeParticleSystem.ParticleImage = ResourceManager.GetResourcePath ("smoke.png"); smokeHandle.AddParticleSystem (smokeParticleSystem); var engineCar = scene.RootNode.FindChildNode ("EngineCar", false); var wagon1 = scene.RootNode.FindChildNode ("Wagon1", false); var wagon2 = scene.RootNode.FindChildNode ("Wagon2", false); max = SCNVector3.Zero; min = SCNVector3.Zero; engineCar.GetBoundingBox (ref min, ref max); var wmax = SCNVector3.Zero; var wmin = SCNVector3.Zero; wagon1.GetBoundingBox (ref wmin, ref wmax); var anchorA = new SCNVector3 (max.X, min.Y, 0f); var anchorB = new SCNVector3 (wmin.X, wmin.Y, 0f); var joint = SCNPhysicsBallSocketJoint.Create (engineCar.PhysicsBody, anchorA, wagon1.PhysicsBody, anchorB); scene.PhysicsWorld.AddBehavior (joint); joint = SCNPhysicsBallSocketJoint.Create (wagon1.PhysicsBody, new SCNVector3 (wmax.X + 0.1f, wmin.Y, 0f), wagon2.PhysicsBody, new SCNVector3 (wmin.X - 0.1f, wmin.Y, 0f) ); scene.PhysicsWorld.AddBehavior (joint); }
private void ReorientCarIfNeeded () { var rnd = new Random (); SCNNode car = vehicleNode.PresentationNode; SCNVector3 carPos = car.Position; ticks++; if (ticks == 30) { SCNMatrix4 t = car.WorldTransform; if (t.M22 <= 0.1f) { check++; if (check == 3) { tryVar++; if (tryVar == 3) { tryVar = 0; vehicleNode.Rotation = new SCNVector4 (0f, 0f, 0f, 0f); vehicleNode.Position = new SCNVector3 (carPos.X, carPos.Y + 10f, carPos.Z); vehicleNode.PhysicsBody.ResetTransform (); } else { float x = -10f * (rnd.Next () / float.MaxValue - 0.5f); float z = -10f * (rnd.Next () / float.MaxValue - 0.5f); var pos = new SCNVector3 (x, 0f, z); vehicleNode.PhysicsBody.ApplyForce (new SCNVector3 (0f, 300f, 0f), pos, true); } check = 0; } } else { check = 0; } ticks = 0; } }
public virtual void DidSimulatePhysics (ISCNSceneRenderer renderer, double timeInSeconds) { float defaultEngineForce = 300.0f; float defaultBrakingForce = 3.0f; float steeringClamp = 0.6f; float cameraDamping = 0.3f; GameView scnView = GameView; float engineForce = 0; float brakingForce = 0; var controllers = GCController.Controllers; float orientation = this.orientation; switch (scnView.TouchesCount) { case 1: engineForce = defaultEngineForce; reactor.BirthRate = reactorDefaultBirthRate; break; case 2: engineForce = -defaultEngineForce; reactor.BirthRate = 0; break; case 3: brakingForce = 100; reactor.BirthRate = 0; break; default: brakingForce = defaultBrakingForce; reactor.BirthRate = 0; break; } if (controllers != null && controllers.Length > 0) { GCController controller = controllers [0]; GCGamepad pad = controller.Gamepad; GCControllerDirectionPad dpad = pad.DPad; if (dpad.Right.IsPressed) { if (orientationCum < 0f) orientationCum *= decrementOrientation; orientationCum += incrementOrientation; if (orientationCum > 1f) orientationCum = 1f; } else if (dpad.Left.IsPressed) { if (orientationCum > 0) orientationCum *= decrementOrientation; orientationCum -= incrementOrientation; if (orientationCum < -1) orientationCum = -1; } else { orientationCum *= decrementOrientation; } } vehicleSteering = -orientation; if (orientation == 0) vehicleSteering *= 0.9f; if (vehicleSteering < -steeringClamp) vehicleSteering = -steeringClamp; if (vehicleSteering > steeringClamp) vehicleSteering = steeringClamp; vehicle.SetSteeringAngle (vehicleSteering, 0); vehicle.SetSteeringAngle (vehicleSteering, 1); vehicle.ApplyEngineForce (engineForce, 2); vehicle.ApplyEngineForce (engineForce, 3); vehicle.ApplyBrakingForce (brakingForce, 2); vehicle.ApplyBrakingForce (brakingForce, 3); ReorientCarIfNeeded (); SCNNode car = vehicleNode.PresentationNode; SCNVector3 carPos = car.Position; var targetPos = new SCNVector3 (carPos.X, 30f, carPos.Z + 25f); var cameraPos = new SCNVector3 (cameraNode.Position); cameraPos = SCNVector3.Add (cameraPos, cameraDamping * (SCNVector3.Subtract (targetPos, cameraPos))); cameraNode.Position = cameraPos; if (scnView.InCarView) { var frontPosition = scnView.PointOfView.PresentationNode.ConvertPositionToNode (new SCNVector3 (0f, 0f, -30f), null); spotLightNode.Position = new SCNVector3 (frontPosition.X, 80f, frontPosition.Z); spotLightNode.Rotation = new SCNVector4 (1f, 0f, 0f, -(float)Math.PI / 2f); } else { spotLightNode.Position = new SCNVector3 (carPos.X, 80f, carPos.Z + 30f); spotLightNode.Rotation = new SCNVector4 (1f, 0f, 0f, -(float)(Math.PI / 2.8)); } var overlayScene = (OverlayScene)scnView.OverlayScene; overlayScene.SpeedNeedle.ZRotation = -(vehicle.SpeedInKilometersPerHour * (float)Math.PI / maxSpeed); }
public SCNNode CreateLevel () { RootNode = new SCNNode (); // load level dae and add all root children to the scene. var options = new SCNSceneLoadingOptions { ConvertToYUp = true }; SCNScene scene = SCNScene.FromFile ("level", GameSimulation.PathForArtResource ("level/"), options); foreach (SCNNode node in scene.RootNode.ChildNodes) RootNode.AddChildNode (node); // retrieve the main camera Camera = RootNode.FindChildNode ("camera_game", true); // create our path that the player character will follow. CalculatePathPositions (); // Sun/Moon light SunLight = RootNode.FindChildNode ("FDirect001", true); SunLight.EulerAngles = new SCNVector3 (7.1f * (nfloat)Math.PI / 4, (nfloat)Math.PI / 4, 0f); SunLight.Light.ShadowSampleCount = 1; lightOffsetFromCharacter = new SCNVector3 (1500f, 2000f, 1000f); //workaround directional light deserialization issue SunLight.Light.ZNear = 100f; SunLight.Light.ZFar = 5000f; SunLight.Light.OrthographicScale = 1000f; // Torches var torchesPos = new float[] { 0f, -1f, 0.092467f, -1f, -1f, 0.5f, 0.792f, 0.95383f }; for (int i = 0; i < torchesPos.Length; i++) { if (torchesPos [i] != -1) { SCNVector3 location = LocationAlongPath (torchesPos [i]); location.Y += 50; location.Z += 150; SCNNode node = CreateTorchNode (); node.Position = location; RootNode.AddChildNode (node); } } // After load, we add nodes that are dynamic / animated / or otherwise not static. CreateLavaAnimation (); CreateSwingingTorch (); AnimateDynamicNodes (); // Create our player character SCNNode characterRoot = GameSimulation.LoadNodeWithName (string.Empty, "art.scnassets/characters/explorer/explorer_skinned.dae"); PlayerCharacter = new PlayerCharacter (characterRoot); TimeAlongPath = 0; PlayerCharacter.Position = LocationAlongPath (TimeAlongPath); PlayerCharacter.Rotation = GetPlayerDirectionFromCurrentPosition (); RootNode.AddChildNode (PlayerCharacter); // Optimize lighting and shadows // only the charadcter should cast shadows foreach (var child in RootNode.ChildNodes) child.CastsShadow = false; foreach (var child in PlayerCharacter.ChildNodes) child.CastsShadow = true; // Add some monkeys to the scene. AddMonkeyAtPosition (new SCNVector3 (0f, -30f, -400f), 0f); AddMonkeyAtPosition (new SCNVector3 (3211f, 146f, -400f), -(nfloat)Math.PI / 4f); AddMonkeyAtPosition (new SCNVector3 (5200f, 330f, 600f), 0f); // Volcano SCNNode oldVolcano = RootNode.FindChildNode ("volcano", true); string volcanoDaeName = GameSimulation.PathForArtResource ("level/volcano_effects.dae"); SCNNode newVolcano = GameSimulation.LoadNodeWithName ("dummy_master", volcanoDaeName); oldVolcano.AddChildNode (newVolcano); oldVolcano.Geometry = null; oldVolcano = newVolcano.FindChildNode ("volcano", true); oldVolcano = oldVolcano.ChildNodes [0]; // Animate our dynamic volcano node. string shaderCode = "uniform float speed;\n" + "_geometry.color = vec4(a_color.r, a_color.r, a_color.r, a_color.r);\n" + "_geometry.texcoords[0] += (vec2(0.0, 1.0) * 0.05 * u_time);\n"; string fragmentShaderCode = "#pragma transparent\n"; // Dim background SCNNode back = RootNode.FindChildNode ("dumy_rear", true); foreach (var child in back.ChildNodes) { child.CastsShadow = false; if (child.Geometry == null) continue; foreach (SCNMaterial material in child.Geometry.Materials) { material.LightingModelName = SCNLightingModel.Constant; material.Multiply.Contents = AppKit.NSColor.FromDeviceWhite (0.3f, 1f); material.Multiply.Intensity = 1; } } SCNNode backMiddle = RootNode.FindChildNode ("dummy_middle", true); foreach (var child in backMiddle.ChildNodes) { if (child.Geometry == null) continue; foreach (SCNMaterial material in child.Geometry.Materials) material.LightingModelName = SCNLightingModel.Constant; } foreach (var child in newVolcano.ChildNodes) foreach (var volc in child.ChildNodes) { if (volc != oldVolcano && volc.Geometry != null) { volc.Geometry.FirstMaterial.LightingModelName = SCNLightingModel.Constant; volc.Geometry.FirstMaterial.Multiply.Contents = AppKit.NSColor.White; volc.Geometry.ShaderModifiers = new SCNShaderModifiers { EntryPointGeometry = shaderCode, EntryPointFragment = fragmentShaderCode }; } } Coconuts = new List<Coconut> (); return RootNode; }
nfloat GetGroundHeight (SCNMatrix4 matrix) { SCNVector3 start = new SCNVector3 (matrix.M41, matrix.M42 + 1000, matrix.M43); SCNVector3 end = new SCNVector3 (matrix.M41, matrix.M42 - 3000, matrix.M43); var options = NSDictionary.FromObjectsAndKeys (new NSObject[] { new NSNumber (GameCollisionCategory.Ground | GameCollisionCategory.Lava), (NSString)"closest" }, new NSObject[] { SCNPhysicsTestKeys.CollisionBitMaskKey, SCNPhysicsTestKeys.SearchModeKey }); SCNHitTestResult[] hits = GameSimulation.Sim.PhysicsWorld.RayTestWithSegmentFromPoint (start, end, options); if (hits == null || hits.Length == 0) return 0; foreach (SCNHitTestResult result in hits) { if (result.Node.PhysicsBody.CategoryBitMask != (GameCollisionCategory.Ground | GameCollisionCategory.Lava)) return result.WorldCoordinates.Y; } return 0; }
public void CollideWithCoconut (SCNNode coconut, SCNVector3 contactPoint) { // No more collisions. Let it bounce away and fade out. coconut.PhysicsBody.CollisionBitMask = 0; coconut.RunAction (SCNAction.Sequence (new SCNAction[] { SCNAction.Wait (1.0), SCNAction.FadeOut (1.0), SCNAction.RemoveFromParentNode () }), () => { Coconuts.Remove ((Coconut)coconut); }); // Decrement score int amountToDrop = Score / 10; amountToDrop = Math.Max (1, amountToDrop); amountToDrop = Math.Min (10, amountToDrop); if (amountToDrop > Score) amountToDrop = Score; Score -= amountToDrop; // Throw bananas float spacing = 40f; for (int x = 0; x < amountToDrop; x++) { SCNNode banana = CreateBanana (); RootNode.AddChildNode (banana); banana.Position = contactPoint; banana.PhysicsBody.CategoryBitMask = GameCollisionCategory.NoCollide; banana.PhysicsBody.CollisionBitMask = GameCollisionCategory.Ground; SCNVector3 endPoint = SCNVector3.Zero; endPoint.X -= (spacing * x) + spacing; SCNAction flyoff = SCNAction.MoveBy (endPoint, MathUtils.RandomPercent () * 0.750f); flyoff.TimingMode = SCNActionTimingMode.EaseInEaseOut; banana.RunAction (flyoff, () => { banana.PhysicsBody.CategoryBitMask = GameCollisionCategory.Banana; banana.PhysicsBody.CollisionBitMask = GameCollisionCategory.Ground | GameCollisionCategory.Player; }); Bananas.Add (banana); } PlayerCharacter.InHitAnimation = true; }
public override void Update (double deltaTime) { SCNMatrix4 mtx = Transform; var gravity = new SCNVector3 (0f, -90f, 0f); var gravitystep = SCNVector3.Multiply (gravity, (nfloat)deltaTime); velocity = SCNVector3.Add (velocity, gravitystep); var minMovement = new SCNVector3 (0f, -50f, 0f); var maxMovement = new SCNVector3 (100f, 100f, 100f); velocity = MathUtils.GetMaxVector (velocity, minMovement); velocity = MathUtils.GetMinVector (velocity, maxMovement); mtx = mtx.TranslateWithVector (velocity); groundPlaneHeight = GetGroundHeight (mtx); if (mtx.M42 < groundPlaneHeight) { if (!Launching && velocity.Y < 0.0f) { if (Jumping) { Jumping = false; if (DustPoof != null) { AddParticleSystem (DustPoof); DustPoof.Loops = false; } PlayLand (); JumpBoost = 0.0f; } } // tie to ground mtx.M42 = groundPlaneHeight; velocity.Y = 0.0f; } Transform = mtx; //-- move the camera SCNNode camera = GameSimulation.Sim.GameLevel.Camera.ParentNode; if (camera != null) { nfloat x = Position.X + ((PlayerWalkDirection == WalkDirection.Right) ? 250 : -250); nfloat y = (Position.Y + 261) - (0.85f * (Position.Y - groundPlaneHeight)); nfloat z = Position.Z + 1500; var pos = new SCNVector3 (x, y, z); SCNMatrix4 desiredTransform = camera.Transform.SetPosition (pos); camera.Transform = MathUtils.Interpolate (camera.Transform, desiredTransform, 0.025f); } }
SCNVector3 LocationAlongPath (nfloat percent) { if (PathPositions.Count <= 3) return SCNVector3.Zero; int numSections = PathPositions.Count - 3; nfloat dist = percent * numSections; int currentPointIndex = (int)Math.Min ((uint)Math.Floor (dist), numSections - 1); dist -= currentPointIndex; var a = new SCNVector3 (PathPositions [currentPointIndex]); var b = new SCNVector3 (PathPositions [currentPointIndex + 1]); var c = new SCNVector3 (PathPositions [currentPointIndex + 2]); var d = new SCNVector3 (PathPositions [currentPointIndex + 3]); var location = new SCNVector3 (); location.X = CatmullRomValue (a.X, b.X, c.X, d.X, dist); location.Y = CatmullRomValue (a.Y, b.Y, c.Y, d.Y, dist); location.Z = CatmullRomValue (a.Z, b.Z, c.Z, d.Z, dist); return location; }
void SetupJumpAnimation () { NSString jumpKey = KeyForAnimationType (CharacterAnimation.Jump); NSString fallingKey = KeyForAnimationType (CharacterAnimation.JumpFalling); NSString landKey = KeyForAnimationType (CharacterAnimation.JumpLand); NSString idleKey = KeyForAnimationType (CharacterAnimation.Idle); CAAnimation jumpAnimation = LoadAndCacheAnimation ("art.scnassets/characters/explorer/jump_start", jumpKey); CAAnimation fallAnimation = LoadAndCacheAnimation ("art.scnassets/characters/explorer/jump_falling", fallingKey); CAAnimation landAnimation = LoadAndCacheAnimation ("art.scnassets/characters/explorer/jump_land", landKey); jumpAnimation.FadeInDuration = 0.15f; jumpAnimation.FadeOutDuration = 0.15f; fallAnimation.FadeInDuration = 0.15f; landAnimation.FadeInDuration = 0.15f; landAnimation.FadeOutDuration = 0.15f; jumpAnimation.RepeatCount = 0; fallAnimation.RepeatCount = 0; landAnimation.RepeatCount = 0; jumpForce = 7.0f; SCNAnimationEventHandler leaveGroundBlock = (animation, animatedObject, playingBackward) => { var jumpVelocity = new SCNVector3 (0f, jumpForce * 2.1f, 0f); velocity = SCNVector3.Add (velocity, jumpVelocity); Launching = false; InJumpAnimation = false; }; SCNAnimationEventHandler pause = (animation, animatedObject, playingBackward) => { mainSkeleton.PauseAnimation (fallingKey); }; jumpAnimation.AnimationEvents = new SCNAnimationEvent[] { SCNAnimationEvent.Create (0.25f, leaveGroundBlock) }; fallAnimation.AnimationEvents = new SCNAnimationEvent[] { SCNAnimationEvent.Create (0.5f, pause) }; // Animation Sequence is to Jump -> Fall -> Land -> Idle. ChainAnimation (jumpKey, fallingKey); ChainAnimation (landKey, idleKey); }
void AddMonkeyAtPosition (SCNVector3 worldPos, nfloat rotation) { if (Monkeys == null) Monkeys = new List<MonkeyCharacter> (); SCNNode palmTree = CreateMonkeyPalmTree (); palmTree.Position = worldPos; palmTree.Rotation = new SCNVector4 (0f, 1f, 0f, rotation); RootNode.AddChildNode (palmTree); MonkeyCharacter monkey = (MonkeyCharacter)palmTree.FindChildNode ("monkey", true); if (monkey != null) Monkeys.Add (monkey); }
private SCNNode NodeWithText (string message, TextType type, int level) { var textNode = SCNNode.Create (); // Bullet if (type == TextType.Bullet) { if (level == 0) message = "• " + message; else { var bullet = SCNNode.Create (); bullet.Geometry = SCNPlane.Create (10.0f, 10.0f); bullet.Geometry.FirstMaterial.Diffuse.Contents = NSColor.FromDeviceRgba ((float)(160 / 255.0), (float)(182 / 255.0), (float)(203 / 255.0), 1); bullet.Position = new SCNVector3 (80, 30, 0); bullet.Geometry.FirstMaterial.LightingModelName = SCNLightingModel.Constant; bullet.Geometry.FirstMaterial.WritesToDepthBuffer = false; bullet.RenderingOrder = 1; textNode.AddChildNode (bullet); message = "\t\t\t\t" + message; } } // Text attributes var extrusion = ExtrusionDepthForTextType (type); var text = SCNText.Create (message, extrusion); textNode.Geometry = text; text.Flatness = TEXT_FLATNESS; text.ChamferRadius = (extrusion == 0 ? 0 : TEXT_CHAMFER); text.Font = FontForTextType (type, level); // Layout var layoutManager = new NSLayoutManager (); var leading = layoutManager.DefaultLineHeightForFont (text.Font); var descender = text.Font.Descender; int newlineCount = ((string[])(((string)text.String.ToString ()).Split ('\n'))).Length; textNode.Pivot = SCNMatrix4.CreateTranslation (0, -descender + newlineCount * leading, 0); if (type == TextType.Chapter) { var min = new SCNVector3 (); var max = new SCNVector3 (); textNode.GetBoundingBox (ref min, ref max); textNode.Position = new SCNVector3 (-11, (-min.Y + textNode.Pivot.M42) * TEXT_SCALE, 7); textNode.Scale = new SCNVector3 (TEXT_SCALE, TEXT_SCALE, TEXT_SCALE); textNode.Rotation = new SCNVector4 (0, 1, 0, (float)(Math.PI / 270.0)); } else { textNode.Position = new SCNVector3 (-16, CurrentBaseline, 0); textNode.Scale = new SCNVector3 (TEXT_SCALE, TEXT_SCALE, TEXT_SCALE); } // Material if (type == TextType.Chapter) { var frontMaterial = SCNMaterial.Create (); var sideMaterial = SCNMaterial.Create (); frontMaterial.Emission.Contents = NSColor.DarkGray; frontMaterial.Diffuse.Contents = ColorForTextType (type, level); sideMaterial.Diffuse.Contents = NSColor.LightGray; textNode.Geometry.Materials = new SCNMaterial[] { frontMaterial, frontMaterial, sideMaterial, frontMaterial, frontMaterial }; } else { // Full white emissive material (visible even when there is no light) textNode.Geometry.FirstMaterial = SCNMaterial.Create (); textNode.Geometry.FirstMaterial.Diffuse.Contents = NSColor.Black; textNode.Geometry.FirstMaterial.Emission.Contents = ColorForTextType (type, level); // Don't write to the depth buffer because we don't want the text to be reflected textNode.Geometry.FirstMaterial.WritesToDepthBuffer = false; // Render last textNode.RenderingOrder = 1; } return textNode; }