/// <summary> /// Set all walls and ledges that are not on the same z index as some entity to ignore it. /// Passed from entity MessageHub subscription and is fired when EntityTracker detects that an entity has changed z index. /// </summary> /// <param name="msg"></param> private void _HandleEntityChangedZIndex(EntityChangedZIndexMessage msg) { RID entityRID = msg.GetEntityRID(); int zIndex = msg.GetZIndex(); GD.PrintS("requested that entity with id: " + entityRID.GetId() + " be moved to collide with segments on z index: " + zIndex); foreach (TileMap tileMap in this._tileMapToWallSB2Ds.Keys) { if (tileMap.ZIndex == zIndex) { Physics2DServer.BodyRemoveCollisionException(this._tileMapToWallSB2Ds[tileMap], entityRID); } else { Physics2DServer.BodyAddCollisionException(this._tileMapToWallSB2Ds[tileMap], entityRID); } } foreach (TileMap tileMap in this._tileMapToLedgeSB2Ds.Keys) { if (tileMap.ZIndex == zIndex) { Physics2DServer.BodyRemoveCollisionException(this._tileMapToLedgeSB2Ds[tileMap], entityRID); GD.PrintS("removed collision with sb2d with id: " + this._tileMapToLedgeSB2Ds[tileMap].GetId()); } else { Physics2DServer.BodyAddCollisionException(this._tileMapToLedgeSB2Ds[tileMap], entityRID); } } }
/// <summary> /// Creates and returns a dictionary that maps a TileMap's StaticBody2D's RID to said TileMap's walls or ledges. /// </summary> /// <param name="tileMaps">List of TileMaps.</param> /// <param name="tileMapToSB2Ds">Map of TileMap to its SB2D, whether its origin was a wall or ledge.</param> /// <param name="perimData">Data of all perimeters of all TileMaps.</param> /// <param name="ledgeData">Data of all ledges of all TileMaps.</param> /// <param name="option">Whether this function is being used to construct segments for walls or ledges.</param> /// <returns>A dictionary that maps a TileMap's SB2D RID to said TileMap's walls.</returns> public static Dictionary<RID, List<SegmentShape2D>> ConstructSB2DSegments(this TileMapList tileMaps, Dictionary<TileMap, RID> tileMapToSB2Ds, PerimeterData perimData, LedgeData ledgeData, StaticBodyOrigin option) { if (tileMaps is null) throw new ArgumentNullException(nameof(tileMaps)); if (tileMapToSB2Ds is null) throw new ArgumentNullException(nameof(tileMapToSB2Ds)); if (perimData is null) throw new ArgumentNullException(nameof(perimData)); if (ledgeData is null) throw new ArgumentNullException(nameof(ledgeData)); var sb2dToSegments = new Dictionary<RID, List<SegmentShape2D>>(); foreach (TileMap tileMap in tileMaps.Values) { RID wall = tileMapToSB2Ds[tileMap]; List<SegmentShape2D> segments = (option == StaticBodyOrigin.Wall) ? _GetWallSegments(tileMaps, tileMap, perimData) : _GetLedgeSegments(tileMaps, tileMap, ledgeData); sb2dToSegments.Add(wall, segments); foreach (SegmentShape2D segment in segments) { Physics2DServer.BodyAddShape(wall, segment.GetRid()); } } return sb2dToSegments; }
/// <summary> /// Free all RIDs stored. /// </summary> private void _FreeRIDs() { var allRIDs = new List <RID>(); allRIDs.AddRange(this._tileMapToFloorArea2Ds.Values); allRIDs.AddRange(this._tileMapToWallSB2Ds.Values); allRIDs.AddRange(this._tileMapToLedgeSB2Ds.Values); foreach (List <ConvexPolygonShape2D> polygons in this._floorArea2DToPolygons.Values) { allRIDs.AddRange(polygons.ConvertAll(x => x.GetRid())); } foreach (List <SegmentShape2D> segments in this._wallSB2DToSegments.Values) { allRIDs.AddRange(segments.ConvertAll(x => x.GetRid())); } foreach (List <SegmentShape2D> segments in this._ledgeSB2DToSegments.Values) { allRIDs.AddRange(segments.ConvertAll(x => x.GetRid())); } foreach (RID rid in allRIDs) { Physics2DServer.FreeRid(rid); } }
public override void _PhysicsProcess(float delta) { // If we aren't falling from the sky, make sure we aren't below the viewport // Purge the leaf if we are // Otherwise, just the skip the rest of the method if (!IsSkyFalling) { if (Body.GlobalPosition.y >= GetViewport().Size.y + 50) { QueueFree(); } return; } // The leaf has arrived into position, stop it from moving anymore and set it to true position if (Body.Position.DistanceTo(Vector2.Zero) <= 5) { Body.LinearVelocity = Vector2.Zero; Body.GravityScale = 0; var transform = (Transform2D)Physics2DServer.BodyGetState(Body.GetRid(), Physics2DServer.BodyState.Transform); transform.origin = new Vector2(0, 0) + GlobalPosition; Physics2DServer.BodySetState(Body.GetRid(), Physics2DServer.BodyState.Transform, transform); IsSkyFalling = false; EmitSignal("SkyLeafDropped"); } }
public Godot.Collections.Dictionary Attack(int x, int y) { var spaceRid = GetWorld2d().Space; var spaceState = Physics2DServer.SpaceGetDirectState(spaceRid); // check the spot to move to var result = spaceState.IntersectRay(new Vector2(x * gridSize + 1, y * gridSize + 1), new Vector2(x * 16 + 2, y * 16 + 2)); return(result); }
public Godot.Collections.Dictionary MoveGridBase(int x, int y) { var spaceRid = GetWorld2d().Space; var spaceState = Physics2DServer.SpaceGetDirectState(spaceRid); // check the spot to move to var result = spaceState.IntersectRay(new Vector2(x * gridSize + 1, y * gridSize + 1), new Vector2(x * 16 + 2, y * 16 + 2)); if (result.Count == 0) // if there is no one there { newPosition = new Vector2(x * gridSize, y * gridSize); gridPosition = new Vector2(x, y); } return(result); }
public static Vector2 SimpleRayCast(CanvasItem spaceNode, Vector2 from, Vector2 to, out bool success) { Physics2DDirectSpaceState physicsState = Physics2DServer.SpaceGetDirectState(spaceNode.GetWorld2d().Space); Dictionary result = physicsState.IntersectRay(from, to, GodotUtility.MakeGDArray(spaceNode)); if (result.ContainsKey("position")) { success = true; return((Vector2)result["position"]); } else { success = false; return(new Vector2()); } }
/// <summary> /// Constructs a dictionary that maps a TileMap to a Physics2DServer-created StaticBody2D (RID). /// Is used for both the walls and ledges dictionaries. /// </summary> /// <param name="tileMaps">List of TileMaps.</param> /// <param name="worldSpace">RID of the World Space.</param> /// <returns>A Dictionary that maps TileMaps to an RID of a StaticBody2D.</returns> public static Dictionary<TileMap, RID> ConstructTileMapCollisionMap(this TileMapList tileMaps, RID worldSpace) { if (tileMaps is null) throw new ArgumentNullException(nameof(tileMaps)); var tileMapToSB2Ds = new Dictionary<TileMap, RID>(); foreach (TileMap tileMap in tileMaps.Values) { RID edgeSB2D = Physics2DServer.BodyCreate(); Physics2DServer.BodySetMode(edgeSB2D, Physics2DServer.BodyMode.Static); Physics2DServer.BodySetSpace(edgeSB2D, worldSpace); Physics2DServer.BodySetState(edgeSB2D, Physics2DServer.BodyState.Transform, Transform2D.Identity); Physics2DServer.BodySetCollisionLayer(edgeSB2D, LayersFuncs.GetLayersValue(Terrain)); Physics2DServer.BodySetCollisionMask(edgeSB2D, LayersFuncs.GetLayersValue(PlayerEntity, NpcEntity)); tileMapToSB2Ds.Add(tileMap, edgeSB2D); } return tileMapToSB2Ds; }
/// <summary> /// Creates a FloorArea2D for each TileMap. /// </summary> /// <param name="tileMaps"></param> /// <param name="worldSpace"></param> /// <returns></returns> public static Dictionary <TileMap, RID> ConstructTileMapFloorMap(this TileMapList tileMaps, RID worldSpace) { if (tileMaps is null) { throw new ArgumentNullException(nameof(tileMaps)); } var tileMapToFloorArea2D = new Dictionary <TileMap, RID>(); foreach (TileMap tileMap in tileMaps.Values) { RID area2d = Physics2DServer.AreaCreate(); Physics2DServer.AreaSetSpace(area2d, worldSpace); tileMapToFloorArea2D[tileMap] = area2d; } return(tileMapToFloorArea2D); }
ConstructFloorPartitions(this TileMapList tileMaps, Dictionary <TileMap, RID> tileMapToFloorArea2Ds, PerimeterData perimData) { if (tileMaps is null) { throw new ArgumentNullException(nameof(tileMaps)); } if (tileMapToFloorArea2Ds is null) { throw new ArgumentNullException(nameof(tileMapToFloorArea2Ds)); } if (perimData is null) { throw new ArgumentNullException(nameof(perimData)); } var floorArea2DToPolygons = new Dictionary <RID, List <ConvexPolygonShape2D> >(); foreach (TileMap tileMap in tileMaps.Values) { RID area2dRID = tileMapToFloorArea2Ds[tileMap]; floorArea2DToPolygons[area2dRID] = new List <ConvexPolygonShape2D>(); Physics2DServer.AreaSetCollisionLayer(area2dRID, LayersFuncs.GetLayersValue(Terrain)); Physics2DServer.AreaSetCollisionMask(area2dRID, LayersFuncs.GetLayersValue(PlayerEntity, NpcEntity)); int maxTileGroups = perimData.GetMaxTileGroup(tileMap); for (int tileGroup = 0; tileGroup < maxTileGroups; tileGroup++) { int maxHoleGroups = perimData.GetMaxHoleGroup(tileMap, tileGroup); var allPerims = new List <Vector2> [maxHoleGroups]; for (int holeGroup = 0; holeGroup < maxHoleGroups; holeGroup++) { //put all perims (outer and hole) from one tile group into a single array of lists (gods help me) for partitioning EdgeCollection <TileEdge> edgeColl = perimData.GetEdgeCollection(tileMap, tileGroup, holeGroup); allPerims[holeGroup] = new List <Vector2>(edgeColl.GetSimplifiedPerim()); } List <ConvexPolygonShape2D> partitionedRectangles = _PartitionPolygonToRectangles(allPerims); foreach (ConvexPolygonShape2D shape in partitionedRectangles) { Physics2DServer.AreaAddShape(area2dRID, shape.GetRid()); GD.PrintS("added shape " + shape.GetRid().GetId() + " to area: " + area2dRID.GetId()); } floorArea2DToPolygons[area2dRID].AddRange(partitionedRectangles); } } return(floorArea2DToPolygons); }
public Godot.Collections.Dictionary AttackColumn(int x, int y, bool up) { var spaceRid = GetWorld2d().Space; var spaceState = Physics2DServer.SpaceGetDirectState(spaceRid); var rayStart = new Vector2(16 * x + 8, 16 * y + 8); // check the spot to move to var rayEnd = new Vector2(0, 0); if (up) { rayEnd = new Vector2(16 * x + 8, 8); } else { rayEnd = new Vector2(16 * x + 8, 16 * 20 + 8); } var result = spaceState.IntersectRay(rayStart, rayEnd); return(result); }
public static RayCastHitInfo RayCastObject(CanvasItem spaceNode, Vector2 from, Vector2 to, out bool success) { Physics2DDirectSpaceState physicsState = Physics2DServer.SpaceGetDirectState(spaceNode.GetWorld2d().Space); Dictionary result = physicsState.IntersectRay(from, to, GodotUtility.MakeGDArray(spaceNode)); if (result.ContainsKey("position")) { success = true; RayCastHitInfo info = new RayCastHitInfo(); info.position = (Vector2)result["position"]; if (result.ContainsKey("collider")) { info.collider = (Godot.Object)result["collider"]; } return(info); } else { success = false; return(null); } }
/// <summary> /// Should be called whenever loaded world changes. /// Resets all wall and ledge physics bodies and prepares new ones to be filled by TileController. /// </summary> /// <param name="tileMaps">List of TileMaps which are guaranteed to have a unique Z index.</param> /// <param name="perimData">Data of all perimeters of all TileMaps.</param> /// <param name="ledgeData">Data of all ledges of all TileMaps.</param> /// <param name="worldSpace">Current world space.</param> public void LoadWorld(TileMapList tileMaps, PerimeterData perimData, LedgeData ledgeData, RID worldSpace) { if (tileMaps == null) { throw new ArgumentNullException(nameof(tileMaps), "Attempted to load world with no tilemaps."); } this._tileMapToFloorArea2Ds = tileMaps.ConstructTileMapFloorMap(worldSpace); this._tileMapToWallSB2Ds = tileMaps.ConstructTileMapCollisionMap(worldSpace); this._tileMapToLedgeSB2Ds = tileMaps.ConstructTileMapCollisionMap(worldSpace); this._floorArea2DToPolygons = tileMaps.ConstructFloorPartitions(this._tileMapToFloorArea2Ds, perimData); this._wallSB2DToSegments = tileMaps.ConstructSB2DSegments(this._tileMapToWallSB2Ds, perimData, ledgeData, CollisionConstructor.StaticBodyOrigin.Wall); this._ledgeSB2DToSegments = tileMaps.ConstructSB2DSegments(this._tileMapToLedgeSB2Ds, perimData, ledgeData, CollisionConstructor.StaticBodyOrigin.Ledge); this._toEntityHub.Publish(new FloorsConstructedMessage(this, this._tileMapToFloorArea2Ds)); foreach (TileMap tileMap in tileMaps.Values) { GD.PrintS("TileMapToFloorArea2Ds RID for tilemap with zIndex " + tileMap.ZIndex + ": " + this._tileMapToFloorArea2Ds[tileMap].GetId()); //GD.PrintS("TileMapToWallSB2Ds RID for tilemap with zIndex " + tileMap.ZIndex + ": " + this.tileMapToWallSB2Ds[tileMap].GetId()); //GD.PrintS("TileMapToLedgeSB2Ds RID for tilemap with zIndex " + tileMap.ZIndex + ": " + this.tileMapToLedgeSB2Ds[tileMap].GetId()); RID floorRID = this._tileMapToFloorArea2Ds[tileMap]; RID wallRID = this._tileMapToWallSB2Ds[tileMap]; RID ledgeRID = this._tileMapToLedgeSB2Ds[tileMap]; GD.PrintS("floorArea2DToPolygons count: " + this._floorArea2DToPolygons[floorRID].Count); GD.PrintS("wallSB2DToSegments count: " + this._wallSB2DToSegments[wallRID].Count); GD.PrintS("ledgeSB2DToSegments count: " + this._ledgeSB2DToSegments[ledgeRID].Count); this._area2DMonitors[floorRID.GetId()] = new Area2DMonitor(floorRID, tileMap.ZIndex, this._floorArea2DToPolygons[floorRID], this._toEntityHub); Physics2DServer.AreaSetMonitorCallback(floorRID, this._area2DMonitors[floorRID.GetId()], nameof(Area2DMonitor.OnAreaCallback)); } this._toEntityHub.Publish(new AreaMonitorsSetupMessage(this)); GD.PrintS("published areamonitor msg"); }