/// <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 } }
public SAA_JumpAround() { LKernel.GetG<InputMain>().OnKeyboardPress_Anything += OnKeyboardPress; tr = new TriggerRegion("RiverTriggerRegion", new Vector3(-12.4589f, 2.30107f, -138.952f), new Quaternion(-0.00359472f, 0.000143133f, 0.999202f, 0.0397857f), new BoxShape(10.9985f, 2.71301f, 32.6104f)); tr.OnTrigger += new TriggerReportEvent(tr_OnTrigger); }
/// <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(); } }
/// <summary> /// Make some trigger regions - a long box, a sphere, and a rotated box /// </summary> public TriggerRegionsTest() { var reporter = LKernel.GetG<TriggerReporter>(); tr1 = new TriggerRegion("test trigger area", new Vector3(5, 3, 30), new BoxShape(10, 3, 3)); reporter.AddEvent(tr1.Name, doSomething); #if DEBUG tr2 = new TriggerRegion("test trigger area 2", new Vector3(-5, 2, 7), new SphereShape(1)); reporter.AddEvent(tr2.Name, doSomething); tr3 = new TriggerRegion("test trigger area 3", new Vector3(-35, 3.5f, 0), new Vector3(0, 45, 0).DegreeVectorToGlobalQuaternion(), new BoxShape(4, 4, 4)); reporter.AddEvent(tr3.Name, doSomething); #endif }
public static TriggerRegion CreateBoxTriggerRegion(string name, TriggerReportEvent trh, Vector3 dimensions, Vector3 position, Quaternion orientation) { var csm = LKernel.GetG<CollisionShapeManager>(); CollisionShape shape; if (!csm.TryGetShape(name, out shape)) { shape = new BoxShape(dimensions); csm.RegisterShape(name, shape); } var tr = new TriggerRegion(name, position, orientation, shape); tr.OnTrigger += trh; AddToDispose(tr, trh); return tr; }
public static TriggerRegion CreateCapsuleTriggerRegion( string name, TriggerReportEvent trh, float radius, float height, Vector3 position, Quaternion orientation) { var csm = LKernel.GetG<CollisionShapeManager>(); CollisionShape shape; if (!csm.TryGetShape(name, out shape)) { shape = new CapsuleShape(radius, height); csm.RegisterShape(name, shape); } var tr = new TriggerRegion(name, position, orientation, shape); tr.OnTrigger += trh; AddToDispose(tr, trh); return tr; }
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; } }
private float MakeOffset(Vector3 relativePos, TriggerRegion region) { float offset = relativePos.z / (region.Width * 2); //System.Console.WriteLine(relativePos.z + " | " + region.Width + " | " + offset); /*if (offset < -0.75f) return -0.75f; else if (offset > 0.75f) return 0.75f; else*/ return offset; }
/// <summary> /// Parses the level's .tr file (if it has one) and sets up the AI trigger regions /// </summary> private void OnLevelLoad(LevelChangedEventArgs eventArgs) { if (eventArgs.NewLevel.Type != LevelType.Race) return; nextTriggerRegions = new Dictionary<TriggerRegion, TriggerRegion>(); /* * threshold * id idTO height width posX posY posZ orientX orientY orientZ orientW */ if (File.Exists("media/worlds/" + eventArgs.NewLevel.Name + ".tr")) { var collisionShapeMgr = LKernel.GetG<CollisionShapeManager>(); var tempDic = new Dictionary<TriggerRegion, int>(); var triggerRegions = new Dictionary<int, TriggerRegion>(); using (StreamReader reader = new StreamReader("media/worlds/" + eventArgs.NewLevel.Name + ".tr")) { float threshold = float.Parse(reader.ReadLine()); string line; while ((line = reader.ReadLine()) != null) { // ignore comments if (line.StartsWith("//")) continue; string[] parts = line.Split(' '); if (parts.Length == 11) { int id = int.Parse(parts[0], culture); int idTo = int.Parse(parts[1], culture); Vector3 dims = new Vector3( threshold, float.Parse(parts[2], culture), float.Parse(parts[3], culture)); Vector3 pos = new Vector3( float.Parse(parts[4], culture), float.Parse(parts[5], culture), float.Parse(parts[6], culture)); Quaternion orient = new Quaternion( float.Parse(parts[7], culture), float.Parse(parts[8], culture), float.Parse(parts[9], culture), float.Parse(parts[10], culture)); CollisionShape shape; if (!collisionShapeMgr.TryGetShape(parts[2] + parts[3], out shape)) { shape = new BoxShape(dims); collisionShapeMgr.RegisterShape(parts[2] + parts[3], shape); } TriggerRegion tr = new TriggerRegion("AITriggerRegion" + id, pos, orient, shape); triggerRegions[id] = tr; tempDic[tr] = idTo; } } } foreach (var kvp in tempDic) { nextTriggerRegions[kvp.Key] = triggerRegions[kvp.Value]; } tempDic.Clear(); triggerRegions.Clear(); LKernel.GetG<TriggerReporter>().OnTriggerEnter += OnTriggerEnter; } }
/// <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> /// Shortcut method to add something to the dispose queue. /// </summary> static void AddToDispose(TriggerRegion region, TriggerReportEvent handler) { toDispose.Add(new Pair<TriggerRegion, TriggerReportEvent>(region, handler)); }
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(); } }