public void AddObjectsIntersectingShape(IList list, IShape shape) { if (_objects == null) { return; } for (var i = 0; i < _objects.Count; i++) { GameObject2D obj = _objects[i]; Rectangle bounds = obj.GetBoundsForQuadTree(); if (shape.Intersects(ref bounds)) { list.Add(obj); } } if (ChildNodes == null) { return; } for (var i = 0; i < ChildNodes.Length; i++) { WorldTree2DNode node = ChildNodes[i]; if (shape.Intersects(ref node.Bounds)) { node.AddObjectsIntersectingShape(list, shape); } } }
public WorldTree2DNode AddObject(Rectangle bounds, GameObject2D obj) { _objects ??= new List <GameObject2D>(); if (_objects.Count + 1 > Capacity && ChildNodes == null && MaxDepth > 0) { float halfWidth = Bounds.Width / 2; float halfHeight = Bounds.Height / 2; ChildNodes = new WorldTree2DNode[4]; ChildNodes[0] = new WorldTree2DNode(this, new Rectangle(Bounds.X, Bounds.Y, halfWidth, halfHeight), Capacity, MaxDepth - 1); ChildNodes[1] = new WorldTree2DNode(this, new Rectangle(Bounds.X + halfWidth, Bounds.Y, halfWidth, halfHeight), Capacity, MaxDepth - 1); ChildNodes[2] = new WorldTree2DNode(this, new Rectangle(Bounds.X, Bounds.Y + halfHeight, halfWidth, halfHeight), Capacity, MaxDepth - 1); ChildNodes[3] = new WorldTree2DNode(this, new Rectangle(Bounds.X + halfWidth, Bounds.Y + halfHeight, halfWidth, halfHeight), Capacity, MaxDepth - 1); WorldTree2DNode subNode = GetNodeForBounds(bounds); return(subNode.AddObject(bounds, obj)); } Debug.Assert(_objects.IndexOf(obj) == -1); _objects.Add(obj); return(this); }
public async Task InitAsync() { var profiler = Stopwatch.StartNew(); // Add all serialized objects, and start loading their assets. var objectAssetTasks = new Task[ObjectsToSerialize.Count + _objectsToAdd.Count]; for (var i = 0; i < ObjectsToSerialize.Count; i++) { GameObject2D obj = ObjectsToSerialize[i]; objectAssetTasks[i] = obj.LoadAssetsAsync(); obj.MapFlags |= Map2DObjectFlags.Serializable; _objects.Add(obj); } // Add non serialized object that were added before map init. int taskIdx = ObjectsToSerialize.Count; while (_objectsToAdd.TryDequeue(out GameObject2D? obj)) { objectAssetTasks[taskIdx] = obj.LoadAssetsAsync(); taskIdx++; _objects.Add(obj); } // Load tile data in parallel. if (TileData != null) { Debug.Assert((TileData.SizeInTiles * TileData.TileSize).SmallerOrEqual(MapSize), "Tiles outside map."); await TileData.LoadTileDataAsync(); } await Task.WhenAll(objectAssetTasks); // Now that all assets are loaded, init the objects. foreach (GameObject2D obj in GetObjects()) { obj.Init(this); } // Wait for the GLThread work queue to empty up. // This ensures that all assets (texture uploads etc) and stuff are loaded. while (!GLThread.Empty) { await Task.Delay(1); } // Call late init and add to the world tree. _worldTree = InitWorldTree(); foreach (GameObject2D obj in GetObjects()) { obj.LateInit(); _worldTree.AddObjectToTree(obj); obj.ObjectState = ObjectState.Alive; // Record initial positions of named objects as named points. if (!string.IsNullOrEmpty(obj.ObjectName)) { if (!NamedPoints.ContainsKey(obj.ObjectName)) { NamedPoints.Add(obj.ObjectName, obj.Position2); } else { Engine.Log.Warning($"Duplicate object name - {obj.ObjectName}", MessageSource.Game, true); } } } await PostMapLoad(); Update(0); // Run the update tick once to prevent some flickering on first update. Initialized = true; Engine.Log.Info($"Map {MapName} loaded in {profiler.ElapsedMilliseconds}ms", "Map2D"); }
public void RemoveObject(GameObject2D obj) { _objects?.Remove(obj); }