public SFXCoordinator(AVAudioEnvironmentNode audioEnvironment) : base() { this.AudioEnvironment = audioEnvironment; this.loadQueue.DispatchAsync(() => { foreach (var file in preloadAudioFiles) { this.PrepareAudioFile(file); } }); // Because the coordinate space is scaled, let's apply some adjustments to the // distance attenuation parameters to make the distance rolloff sound more // realistic. this.AudioEnvironment.DistanceAttenuationParameters.ReferenceDistance = 5f; this.AudioEnvironment.DistanceAttenuationParameters.MaximumDistance = 40f; this.AudioEnvironment.DistanceAttenuationParameters.RolloffFactor = 1f; this.AudioEnvironment.DistanceAttenuationParameters.DistanceAttenuationModel = AVAudioEnvironmentDistanceAttenuationModel.Inverse; this.UpdateEffectsVolume(); // When the route changes, we need to reload our audio samplers because sometimes those // audio units are being reset. NSNotificationCenter.DefaultCenter.AddObserver(AVAudioSession.RouteChangeNotification, this.HandleRouteChange); // Subscribe to notifications of user defaults changing so that we can apply them to // sound effects. NSNotificationCenter.DefaultCenter.AddObserver(NSUserDefaults.DidChangeNotification, this.HandleDefaultsDidChange); NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidEnterBackgroundNotification, this.HandleAppDidEnterBackground); }
public Catapult(SCNNode node, SFXCoordinator sfxCoordinator, int identifier, Dictionary <string, object> gamedefs) : base(node, null, gamedefs, true, false) { this.Base = node; this.audioEnvironment = sfxCoordinator.AudioEnvironment; // Base teamID and name off looking up teamA or teamB folder in the level parents // This won't work on the old levels. this.Team = this.Base.GetTeam(); this.TeamName = this.Team.GetDescription(); // have team id established this.Base.SetPaintColors(); // correct for the pivot point to place catapult flat on ground this.Base.Position = new SCNVector3(this.Base.Position.X, this.Base.Position.Y - 0.13f, this.Base.Position.Z); // highlight setup this.HighlightObject = node.FindChildNode("Highlight", true); if (this.HighlightObject != null) { this.HighlightObject = this.HighlightObject.FindNodeWithGeometry(); } // hide the highlights on load if (this.HighlightObject != null) { this.HighlightObject.Hidden = true; } if (this.HighlightObject?.Geometry?.FirstMaterial?.Diffuse?.Contents is UIColor color) { this.highlightColor = color; } // they should only have y orientation, nothing in x or z // current scene files have the catapults with correct orientation, but the // eulerAngles are different - x and z are both π, y is within epsilon of 0 // That's from bad decomposition of the matrix. Need to restore the eulerAngles from the source. // Especially if we have animations tied to the euler angles. if (Math.Abs(node.EulerAngles.X) > 0.001f || Math.Abs(node.EulerAngles.Z) > 0.001f) { //Console.WriteLine("Catapult can only have y rotation applied"); } // where to place the ball so it sits on the strap this.catapultStrap = this.Base.FindChildNode("catapultStrap", true); if (this.catapultStrap == null) { throw new Exception("No node with name catapultStrap"); } // this only rotates, and represents the center of the catapult through which to fire this.pullOrigin = this.Base.FindChildNode("pullOrigin", true); if (this.pullOrigin == null) { throw new Exception("No node with name pullOrigin"); } // This is a rope simulation meant for a fixed catapult, the catapult rotates. this.rope = new CatapultRope(node); // attach ball to the inactive strap, search for ballOriginInactiveBelow this.ballOriginInactiveBelow = this.Base.FindChildNode("ballOriginInactiveBelow", true); if (this.ballOriginInactiveBelow == null) { throw new Exception("No node with name ballOriginInactiveBelow"); } this.ballOriginInactiveAbove = this.Base.FindChildNode("ballOriginInactiveAbove", true); if (this.ballOriginInactiveAbove == null) { throw new Exception("No node with name ballOriginInactiveAbove"); } // ball will be made visible and drop once projectile is set and cooldown exceeded this.StrapVisible = StrapVisible.Visible; this.CatapultId = identifier; this.Base.SetValueForKey(NSObject.FromObject(this.CatapultId), new NSString(Catapult.CollisionKey)); this.AudioPlayer = new CatapultAudioSampler(this.Base, sfxCoordinator); // use the teamID to set the collision category mask if (this.PhysicsNode?.PhysicsBody != null) { if (this.Team == Team.TeamA) { this.PhysicsNode.PhysicsBody.CategoryBitMask = (int)CollisionMask.CatapultTeamA; var collisionBitMask = (CollisionMask)(int)this.PhysicsNode.PhysicsBody.CollisionBitMask; this.PhysicsNode.PhysicsBody.CollisionBitMask = (nuint)(int)(collisionBitMask | CollisionMask.CatapultTeamB); } else if (this.Team == Team.TeamB) { this.PhysicsNode.PhysicsBody.CategoryBitMask = (int)CollisionMask.CatapultTeamB; var collisionBitMask = (CollisionMask)(int)this.PhysicsNode.PhysicsBody.CollisionBitMask; this.PhysicsNode.PhysicsBody.CollisionBitMask = (nuint)(int)(collisionBitMask | CollisionMask.CatapultTeamA); } } }