/// <summary> /// Calculates the next waypoint we should drive to /// </summary> /// <param name="enteredRegion">The trigger region that fired the collision event</param> /// <param name="nextRegion">The next trigger region we should drive to</param> /// <param name="info"> /// Contains some information about when we drove into the previous trigger region. /// If this is null, then it's the initial waypoint we got when we loaded the level. /// </param> public void CalculateNewWaypoint(TriggerRegion enteredRegion, TriggerRegion nextRegion, CollisionReportInfo info) { // have to check for this because trigger regions like sending duplicate events // also we check against the previous region in situations where the kart is in two regions at once if ((nextRegion != CurrentRegion && nextRegion != PreviousRegion && enteredRegion != PreviousRegion) || info == null) { // do we need to do all of the transform stuff? it's accurate, but do we need to be particularly accurate? // forward is -X float offset; if (info == null || info.Position == null) { // when we're starting, we'll just use our kart's position for things Vector3 relativePos = nextRegion.Ghost.WorldTransform.InverseAffine() * Kart.ActualPosition; offset = MakeOffset(relativePos, nextRegion); } else { // otherwise calculate using the region we just entered Vector3 relativePos = enteredRegion.Ghost.WorldTransform.InverseAffine() * info.Position.Value; offset = MakeOffset(relativePos, enteredRegion); } nextWaypoint = nextRegion.Ghost.WorldTransform * new Vector3(0, 0, offset * nextRegion.Width); nextWaypoint.y = Kart.ActualPosition.y; // update the region pointers PreviousRegion = enteredRegion; CurrentRegion = nextRegion; // update this axis' position #if DEBUG //axis.RootNode.Position = nextWaypoint; //axis.RootNode.Orientation = nextRegion.Body.Orientation; nextRegion.CycleToNextColor(); #endif } }
/// <summary> /// output some text, show/hide a dialogue, and change the color of the region /// </summary> void doSomething(TriggerRegion region, RigidBody otherBody, TriggerReportFlags flags, CollisionReportInfo info) { if (flags.HasFlag(TriggerReportFlags.Enter)) { Console.WriteLine(otherBody.GetName() + " has entered trigger area \"" + region.Name + "\""); // cycle through the balloon colors region.CycleToNextColor(); } else { Console.WriteLine(otherBody.GetName() + " has left trigger area \"" + region.Name + "\""); region.CycleToNextColor(); } }
void OnCol(CollisionReportInfo info) { if (info.FirstGroup == PonykartCollisionGroups.Karts) { foreach (Player p in LKernel.GetG<PlayerManager>().Players) { if (info.FirstObject.GetHashCode() == p.Kart.Body.GetHashCode() && info.SecondObject.GetHashCode() == this.Body.GetHashCode()) { p.hasItem = true; ui.SetItemLevel(1); ui.SetItemImage(itemName); p.heldItem = itemName; LKernel.GetG<SoundMain>().Play3D("Item Get.wav", p.NodePosition, false); //DummyItem dummy = new DummyItem(itemName, p); LKernel.GetG<CollisionReporter>().RemoveEvent(PonykartCollisionGroups.Karts, PonykartCollisionGroups.Default, OnCol); Dispose(); } } } }
void CrossFinishLine(TriggerRegion region, RigidBody otherBody, TriggerReportFlags flags, CollisionReportInfo info) { // get the kart out of the object Kart kart = ((CollisionObjectDataHolder) otherBody.UserObject).GetThingAsKart(); // make sure it's passed the halfway point first if (kart != null && lapData[kart.OwnerID].first) { lapData[kart.OwnerID].first = false; if (lapData[kart.OwnerID].second >= 2) { // we have completed three laps, fire the finish event if (OnFinish != null) OnFinish(kart); // if it's the player, fire its event if (kart == LKernel.GetG<PlayerManager>().MainPlayer.Kart) { if (OnPlayerFinish != null) OnPlayerFinish(kart); } // and if it's the first one to finish, fire that one too if (!anyoneFinishedYet) { anyoneFinishedYet = true; if (OnFirstFinish != null) OnFirstFinish(kart); } } else { // increment the counter lapData[kart.OwnerID].second++; // don't fire the event when we just cross the line when the race starts if (lapData[kart.OwnerID].second != 1) { // we have completed a lap, fire the lap event if (OnLap != null) OnLap(kart, lapData[kart.OwnerID].second); if (kart == LKernel.GetG<PlayerManager>().MainPlayer.Kart) { if (OnPlayerLap != null) OnPlayerLap(kart, lapData[kart.OwnerID].second); } } } } }
/// <summary> /// Need to check somewhere else on the track otherwise we can just drive in circles over the finish line /// </summary> void Halfway(TriggerRegion region, RigidBody otherBody, TriggerReportFlags flags, CollisionReportInfo info) { Kart kart = ((CollisionObjectDataHolder) otherBody.UserObject).GetThingAsKart(); if (kart != null && !lapData[kart.OwnerID].first) { lapData[kart.OwnerID].first = true; } }
void OnCol(CollisionReportInfo info) { //may be useful later: info.FirstObject.CheckCollideWith //Do nothing if we're not looking at ourselves //if(info.SecondObject.GetHashCode() == this.Kart.Body.GetHashCode()) //{ // //normalised copy of the velocity vector // Vector3 velNorm = this.Kart.Vehicle.ForwardVector.NormalisedCopy; // Vector3 contactNorm; // //The point of contact // //Access only if exists // if (info.Position.HasValue) // { // contactNorm = info.Position.Value.NormalisedCopy; // //1.5707 rad = 90 deg // //I'm separating the space around the kart into four chunks // if (velNorm.DirectionEquals(contactNorm, new Radian(1.5707f))) // { // this.OnCollideFront(); // } // } //} }
/// <summary> /// Runs whenever we get a collision event from trigger/kart collisions /// </summary> void CollisionEvent(CollisionReportInfo info) { // get our objects RigidBody kartBody; GhostObject triggerBody; if (info.FirstObject.GetCollisionGroup() == PonykartCollisionGroups.Triggers) { //ghost = info.SecondObject as GhostObject; triggerBody = info.FirstObject as GhostObject; kartBody = info.SecondObject as RigidBody; } else { triggerBody = info.SecondObject as GhostObject; kartBody = info.FirstObject as RigidBody; } // get our region TriggerRegion region; if (Regions.TryGetValue(triggerBody.GetName(), out region)) { // started touching = enter if (info.Flags == ObjectTouchingFlags.StartedTouching) { region.CurrentlyCollidingWith.Add(kartBody); region.InvokeTrigger(kartBody, TriggerReportFlags.Enter, info); if (OnTriggerContact != null) OnTriggerContact(region, kartBody, TriggerReportFlags.Enter, info); if (OnTriggerEnter != null) OnTriggerEnter(region, kartBody, TriggerReportFlags.Enter, info); } // stopped touching = leave else if (info.Flags == ObjectTouchingFlags.StoppedTouching) { region.CurrentlyCollidingWith.Remove(kartBody); region.InvokeTrigger(kartBody, TriggerReportFlags.Leave, info); if (OnTriggerContact != null) OnTriggerContact(region, kartBody, TriggerReportFlags.Leave, info); if (OnTriggerLeave != null) OnTriggerLeave(region, kartBody, TriggerReportFlags.Leave, info); } } }
/// <summary> /// When a kart enters a trigger region, check that it's one of the AI ones, and if so, tell the kart where to go next /// </summary> private void OnTriggerEnter(TriggerRegion currentRegion, RigidBody otherBody, TriggerReportFlags flags, CollisionReportInfo info) { TriggerRegion nextRegion; if (nextTriggerRegions.TryGetValue(currentRegion, out nextRegion)) { Kart kart = null; if (otherBody.UserObject is CollisionObjectDataHolder) { kart = (otherBody.UserObject as CollisionObjectDataHolder).GetThingAsKart(); } if (kart != null && kart.Player.IsComputerControlled) { (kart.Player as ComputerPlayer).CalculateNewWaypoint(currentRegion, nextRegion, info); } } }
/// <summary> /// Run the enter event /// </summary> public void InvokeTrigger(RigidBody otherBody, TriggerReportFlags flags, CollisionReportInfo info) { // at the moment this only triggers when the "main" shape of an actor enters. Do we want to change this? if (OnTrigger != null) { #if DEBUG try { #endif OnTrigger(this, otherBody, flags, info); #if DEBUG } catch (Exception e) { Launch.Log("Exception at TriggerRegion.InvokeTrigger: " + e.Message + " " + e.Source); } #endif } }
void tr_OnTrigger(TriggerRegion region, RigidBody otherBody, TriggerReportFlags flags, CollisionReportInfo info) { var pos = new Vector3(-305.8f, 45.4037f, -693.169f) / 5f; var quat = new Quaternion(0.7143f, 0, -0.6998f, 0); quat = quat * new Quaternion(0, 0, 1, 0); Matrix4 mat = new Matrix4(); mat.MakeTransform(pos, Vector3.UNIT_SCALE, quat); Kart kart = (otherBody.UserObject as CollisionObjectDataHolder).GetThingAsKart(); if (kart != null) { kart.Body.WorldTransform = mat; kart.Body.Activate(); } }
/// <summary> /// Sets up a contact event and then invokes it. /// </summary> private void SetupAndFireEvent(CollisionObject objectA, CollisionObject objectB, Vector3? position, Vector3? normal, ObjectTouchingFlags flags) { PonykartCollisionGroups groupA = objectA.GetCollisionGroup(); PonykartCollisionGroups groupB = objectB.GetCollisionGroup(); //int groupIDA = (int) groupA; //int groupIDB = (int) groupB; CollisionReportInfo info = new CollisionReportInfo { FirstGroup = groupA, SecondGroup = groupB, FirstObject = objectA, SecondObject = objectB, Position = position, Normal = normal, Flags = flags }; FireEvent(info); }
/// <summary> /// invoke an event. /// /// note that it only invokes [a,b] and not [b,a] - if it invokes both, errors will happen /// </summary> private void FireEvent(CollisionReportInfo info) { var e = reporters[(int) info.FirstGroup, (int) info.SecondGroup]; if (e != null) { e(info); } }