public override void StartDrag(RayHitTestParameters ray) { if (_sphereCenter == null || _sphereOrientation == null) { throw new InvalidOperationException("SphereCenter and SphereOrientation need to be set before calling this method"); } if (_dragHitShape == null) { _dragHitShape = new DragHitShape(); } _dragHitShape.SetShape_Sphere(this.SphereCenter, this.Radius); _dragMouseDownClickRay = ray; _dragMouseDownCenterRay = ray; //_dragMouseDownCenterRay = new RayHitTestParameters(this.DragAxis.Origin, ray.Direction); //TODO: the ray through the center of the part really isn't parallel to the click ray (since the perspective camera sees in a cone) // Remember where they clicked (to be able to calculate the rotation in DragItem) Point3D?hitPoint = _dragHitShape.CastRay(ray); if (hitPoint == null) { // This will never happen for sphere _mouseDownHitPoint = new Point3D(0, 0, 0); } else { _mouseDownHitPoint = hitPoint.Value; } _mouseDownOrientation = this.SphereOrientation.ToUnit(); }
private void ChangeDragPlane(RayHitTestParameters clickRay) { _dragHistory.Clear(); if (_selectedItem == null) { _dragPlane = null; return; } //NOTE: This was copied from Game.Newt.v2.GameItems.ShipEditor.Editor.ChangeDragHitShape() Point3D point = _selectedItem.Item.PositionWorld; RayHitTestParameters cameraLookCenter = UtilityWPF.RayFromViewportPoint(_camera, _viewport, new Point(_viewport.ActualWidth * .5d, _viewport.ActualHeight * .5d)); // Come up with the right plane Vector3D standard = Math3D.GetArbitraryOrhonganal(cameraLookCenter.Direction); Vector3D orth = Vector3D.CrossProduct(standard, cameraLookCenter.Direction); ITriangle plane = new Triangle(point, point + standard, point + orth); _dragPlane = new DragHitShape(); _dragPlane.SetShape_Plane(plane); _dragMouseDownClickRay = clickRay; _dragMouseDownCenterRay = new RayHitTestParameters(point, clickRay.Direction); //TODO: the ray through the center of the part really isn't parallel to the click ray (since the perspective camera sees in a cone) }
public AIMousePlate(DragHitShape dragPlane, double scale = 1, double maxXY = 100) { _dragPlane = dragPlane; Scale = scale; MaxXY = maxXY; Position = new Point3D(0, 0, 0); Up = new Vector3D(0, 1, 0); Look = new Vector3D(0, 0, -1); }
public void LeftMouseUp(MouseButtonEventArgs e) { if (_selectedItem != null) { _selectedItem.StopDragging(); } ClearDebugVisuals(); _dragPlane = null; _dragHistory.Clear(); }
public override void StartDrag(RayHitTestParameters ray) { if (this.DragAxis == null) { throw new InvalidOperationException("DragAxis needs to be set before calling this method"); } if (_dragHitShape == null) { _dragHitShape = new DragHitShape(); } _dragHitShape.SetShape_Line(this.DragAxis); _dragMouseDownClickRay = ray; _dragMouseDownCenterRay = new RayHitTestParameters(this.DragAxis.Origin, ray.Direction); //TODO: the ray through the center of the part really isn't parallel to the click ray (since the perspective camera sees in a cone) }
public void UnselectItem() { if (_selectedItem != null) { _selectedItem.Item.PhysicsBody.Disposing -= new EventHandler(PhysicsBody_Disposing); // Let overridden versions of the selected items remove any selection visuals _selectedItem.Dispose(); } ClearDebugVisuals(); _selectedItem = null; _dragPlane = null; _dragHistory.Clear(); }
//TODO: This functionality should be part of MapObjectChaseVelocity private static Point3D?AdjustIfOffPlane(Point3D itemPos, double itemRadius, DragHitShape dragPlane, Point3D?chasePoint) { const double MAXOFFSET = 1.5; const double PERCENTATMAX = .01; // even if they are really far off the plane, don't completely chase the plane, some percent needs to go toward the chase point passed in Point3D?pointOnPlane = dragPlane.CastRay(itemPos); if (pointOnPlane == null) { // Don't know where they are relative to the plane (this should never happen) return(chasePoint); } else if (Math3D.IsNearValue(pointOnPlane.Value, itemPos)) { // They're position is the same as the point on the plane (they are already on the plane) return(chasePoint); } Vector3D vectToPlane = (itemPos - pointOnPlane.Value); double distToPlane = vectToPlane.Length; if (distToPlane < itemRadius * .01) { // They are less than a percent of their body size off the plane, just return the point passed in return(chasePoint); } if (chasePoint == null) { // Null was passed in, just go straight for the plane (this should never happen) return(pointOnPlane); } // Figure out how much to dive for the plane vs go for the chase point double offset = distToPlane / itemRadius; double percent = PERCENTATMAX; if (offset < MAXOFFSET) { // They are less than the max allowable distance from the plane percent = UtilityCore.GetScaledValue_Capped(PERCENTATMAX, 1d, 0, MAXOFFSET, MAXOFFSET - offset); } Vector3D direction = chasePoint.Value - pointOnPlane.Value; return(pointOnPlane.Value + (direction * percent)); }
/// <summary> /// Once the world is created on the worker thread, maps and bots need to be created for each room /// NOTE: This is called from the worker thread /// </summary> private void Arena_WorldCreated(object sender, EventArgs e) { World world = Arena.WorldAccessor.World; #region materials MaterialManager = new MaterialManager(world); MaterialIDs = new MaterialIDs(); // Wall Game.Newt.v2.NewtonDynamics.Material material = new Game.Newt.v2.NewtonDynamics.Material(); material.Elasticity = ItemOptionsArco.ELASTICITY_WALL; MaterialIDs.Wall = MaterialManager.AddMaterial(material); // Bot material = new Game.Newt.v2.NewtonDynamics.Material(); MaterialIDs.Bot = MaterialManager.AddMaterial(material); // Bot Ram material = new Game.Newt.v2.NewtonDynamics.Material(); material.Elasticity = ItemOptionsArco.ELASTICITY_BOTRAM; MaterialIDs.BotRam = MaterialManager.AddMaterial(material); // Exploding Bot material = new Game.Newt.v2.NewtonDynamics.Material(); material.IsCollidable = false; MaterialIDs.ExplodingBot = MaterialManager.AddMaterial(material); // Weapon material = new Game.Newt.v2.NewtonDynamics.Material(); MaterialIDs.Weapon = MaterialManager.AddMaterial(material); // Treasure Box material = new Game.Newt.v2.NewtonDynamics.Material(); MaterialIDs.TreasureBox = MaterialManager.AddMaterial(material); //TODO: Uncomment these // Collisions //_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.Bot, Collision_BotBot); //_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.Weapon, Collision_BotWeapon); //_materialManager.RegisterCollisionEvent(_materialIDs.Weapon, _materialIDs.Weapon, Collision_WeaponWeapon); ////_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.Wall, Collision_BotWall); //_materialManager.RegisterCollisionEvent(_materialIDs.Weapon, _materialIDs.Wall, Collision_WeaponWall); //_materialManager.RegisterCollisionEvent(_materialIDs.Weapon, _materialIDs.TreasureBox, Collision_WeaponTreasureBox); //_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.TreasureBox, Collision_BotTreasureBox); #endregion List <KeepItems2D> keep2Ds = new List <KeepItems2D>(); foreach (var(room, _) in Arena.AllRooms) { #region keep 2D //TODO: drag plane should either be a plane or a large cylinder, based on the current (level|scene|stage|area|arena|map|place|region|zone) // This game is 3D emulating 2D, so always have the mouse go to the XY plane DragHitShape dragPlane = new DragHitShape(); dragPlane.SetShape_Plane(new Triangle(new Point3D(-1, -1, room.Center.Z), new Point3D(1, -1, room.Center.Z), new Point3D(0, 1, room.Center.Z))); // This will keep objects onto that plane using forces (not velocities) KeepItems2D keep2D = new KeepItems2D { SnapShape = dragPlane, }; //keep2D.Add(room.Bot, false); keep2Ds.Add(keep2D); #endregion #region bot ShipCoreArgs core = new ShipCoreArgs() { World = world, Material_Ship = MaterialIDs.Bot, Map = room.Map, }; //BotConstructor_Events events = new BotConstructor_Events(); //events. // Create the bot Bot bot = null; if (RequestCustomBot != null) { bot = RequestCustomBot(core, keep2D, dragPlane, MaterialIDs); } else { BotConstruction_Result construction = BotConstructor.ConstructBot(DNA, core, ShipExtraArgs); bot = new Bot(construction); } // Find some parts BrainNEAT brainPart = bot.Parts.FirstOrDefault(o => o is BrainNEAT) as BrainNEAT; if (brainPart == null) { throw new ApplicationException("Didn't find BrainNEAT part"); } SensorHoming[] homingParts = bot.Parts. Where(o => o is SensorHoming). Select(o => (SensorHoming)o). ToArray(); if (homingParts.Length == 0) { throw new ApplicationException("Didn't find SensorHoming part"); } #endregion room.Bot = bot; room.BrainPart = brainPart; room.HomingParts = homingParts; foreach (SensorHoming homing in homingParts) { homing.HomePoint = room.Center; homing.HomeRadius = (ROOMSIZE / 2d) * Evaluator3.MULT_HOMINGSIZE; } room.Map.AddItem(bot); keep2D.Add(room.Bot, false); } Keep2D = keep2Ds.ToArray(); world.Updated += World_Updated; }
/// <summary> /// This will return a constructed arcbot (arcbots have hardcoded dna) /// </summary> public static BotConstruction_Result GetConstruction(int level, ShipCoreArgs core, ShipExtraArgs extra, DragHitShape dragPlane, bool addHomingSensor) { BotConstructor_Events events = new BotConstructor_Events { InstantiateUnknownPart_Standard = InstantiateUnknownPart_Standard, }; object[] botObjects = new object[] { new ArcBot2_ConstructionProps() { DragPlane = dragPlane, Level = level, }, }; ShipDNA dna = GetDefaultDNA(addHomingSensor); return(BotConstructor.ConstructBot(dna, core, extra, events, botObjects)); }
public ArcBotNPC(BotDNA dna, int level, Point3D position, World world, Map map, KeepItems2D keepItems2D, MaterialIDs materialIDs, Viewport3D viewport, EditorOptions editorOptions, ItemOptionsArco itemOptions, IGravityField gravity, DragHitShape dragPlane, Point3D homingPoint, double homingRadius, bool runNeural, bool repairPartPositions) : base(dna, level, position, world, map, keepItems2D, materialIDs, viewport, editorOptions, itemOptions, gravity, dragPlane, homingPoint, homingRadius, runNeural, repairPartPositions) { }
private void DrawLines_Plate(int numSamples, double half, double lineThickness, AxisFor axisX, AxisFor axisY, AxisFor axisZ) { const double ELAPSEDURATIONSECONDS = 1; // Figure out how wide to make the plate int totalSamples = numSamples * numSamples * numSamples; // numsamples is per axis, so cube it int cellsPerSlice = _field.Size * _field.Size; int numSlices = Convert.ToInt32(Math.Round(Convert.ToDouble(totalSamples) / Convert.ToDouble(cellsPerSlice))); if (numSlices == 0) { numSlices = 1; } int toOffset = numSlices / 2; int fromOffset = numSlices - toOffset - 1; DateTime now = DateTime.UtcNow; bool isOverField = false; if (_mousePoint != null) { #region Snap to mouse // Cast a ray (Copied this from ItemSelectDragLogic.ChangeDragPlane, DragItem) Point3D point = new Point3D(0, 0, 0); RayHitTestParameters cameraLookCenter = UtilityWPF.RayFromViewportPoint(_camera, _viewport, new Point(_viewport.ActualWidth * .5d, _viewport.ActualHeight * .5d)); // Come up with a snap plane Vector3D standard = Math3D.GetArbitraryOrhonganal(cameraLookCenter.Direction); Vector3D orth = Vector3D.CrossProduct(standard, cameraLookCenter.Direction); ITriangle plane = new Triangle(point, point + standard, point + orth); DragHitShape dragPlane = new DragHitShape(); dragPlane.SetShape_Plane(plane); // Cast a ray onto that plane from the current mouse position RayHitTestParameters mouseRay = UtilityWPF.RayFromViewportPoint(_camera, _viewport, _mousePoint.Value); Point3D?hitPoint = dragPlane.CastRay(mouseRay); if (hitPoint != null) { // Find the nearest Z cell double halfSize = (_field.Size * _sizeMult) / 2d; double cellSize = (_field.Size * _sizeMult) / _field.Size; int zIndex = Convert.ToInt32((halfSize - axisZ.GetValue(hitPoint.Value)) / cellSize); if (zIndex >= 0 && zIndex < _field.Size) { isOverField = true; // Cap to field _plateCurrentIndex = _field.Size - zIndex; // it's actually the opposite if (_plateCurrentIndex - fromOffset < 0) { _plateCurrentIndex = fromOffset; } else if (_plateCurrentIndex + toOffset > _field.Size - 1) { _plateCurrentIndex = _field.Size - toOffset - 1; } _sceneRemaining = now + TimeSpan.FromSeconds(ELAPSEDURATIONSECONDS); } } #endregion } if (!isOverField) { #region Shift the plate if (_plateCurrentIndex + toOffset > _field.Size - 1) { _plateCurrentIndex = _field.Size - toOffset - 1; _sceneRemaining = now + TimeSpan.FromSeconds(ELAPSEDURATIONSECONDS); } else if (now > _sceneRemaining) { _plateCurrentIndex--; if (_plateCurrentIndex - fromOffset <= 0) { _plateCurrentIndex = _field.Size - toOffset - 1; } _sceneRemaining = now + TimeSpan.FromSeconds(ELAPSEDURATIONSECONDS); } #endregion } double[] velX = _field.VelocityX; double[] velY = _field.VelocityY; double[] velZ = _field.VelocityZ; bool[] blocked = _field.Blocked; _velocityLines.BeginAddingLines(); for (int z = _plateCurrentIndex - fromOffset; z <= _plateCurrentIndex + toOffset; z++) { for (int x = 0; x < _field.Size; x++) { for (int y = 0; y < _field.Size; y++) { int xRef = -1; int yRef = -1; int zRef = -1; axisX.Set3DIndex(ref xRef, ref yRef, ref zRef, x); axisY.Set3DIndex(ref xRef, ref yRef, ref zRef, y); axisZ.Set3DIndex(ref xRef, ref yRef, ref zRef, z); int index1D = _field.Get1DIndex(xRef, yRef, zRef); if (blocked[index1D]) { continue; } DrawLinesSprtAddLine(xRef, yRef, zRef, index1D, half, lineThickness, velX, velY, velZ); } } } _velocityLines.EndAddingLines(); }