public Index2 PointToMapPosition(Point pt) { if (Map == null) return new Index2(); Index2 ind = new Index2((int)(pt.X / scale + offsetX), (int)(pt.Y / scale + offsetY)); ind.NormalizeXY(new Index2(Map.Planet.Size.X * Chunk.CHUNKSIZE_X, Map.Planet.Size.Y * Chunk.CHUNKSIZE_Y)); return ind; }
/// <summary> /// Interne Methode, in der der zentrale Chunk gesetzt wird. Die Chunks um den Zentrumschunk werden auch nachgeladen falls nötig /// </summary> /// <param name="token">Token, um zu prüfen, ob die aktualisierung abgeborchen werden soll</param> /// <param name="planet">Der Planet, auf dem die Chunks aktualisiert werden sollen</param> /// <param name="index">Der ins Zentrum zu setzende Chunk</param> /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param> private void InternalSetCenter(CancellationToken token, IPlanet planet, Index2 index, Action <bool> successCallback) { if (planet == null) { successCallback?.Invoke(true); return; } List <Index2> requiredChunkColumns = new List <Index2>(); for (int x = -range; x <= range; x++) { for (int y = -range; y <= range; y++) { Index2 local = new Index2(index.X + x, index.Y + y); local.NormalizeXY(planet.Size); requiredChunkColumns.Add(local); } } // Erste Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } foreach (var chunkColumnIndex in requiredChunkColumns .OrderBy(c => index.ShortestDistanceXY(c, new Index2(planet.Size)) .LengthSquared())) { int localX = chunkColumnIndex.X & mask; int localY = chunkColumnIndex.Y & mask; int flatIndex = FlatIndex(localX, localY); IChunkColumn chunkColumn = chunkColumns[flatIndex]; // Alten Chunk entfernen, falls notwendig if (chunkColumn != null && chunkColumn.Index != chunkColumnIndex) { globalCache.Release(planet.Id, chunkColumn.Index, IsPassive); chunkColumns[flatIndex] = null; chunkColumn = null; } // Zweite Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } // Neuen Chunk laden if (chunkColumn == null) { chunkColumn = globalCache.Subscribe(planet.Id, new Index2(chunkColumnIndex), IsPassive); chunkColumns[flatIndex] = chunkColumn; if (chunkColumn == null) { successCallback?.Invoke(false); return; } } // Dritte Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } } successCallback?.Invoke(true); }
/// <summary> /// Interne Methode, in der der zentrale Chunk gesetzt wird. Die Chunks um den Zentrumschunk werden auch nachgeladen falls nötig /// </summary> /// <param name="token">Token, um zu prüfen, ob die aktualisierung abgeborchen werden soll</param> /// <param name="planet">Der Planet, auf dem die Chunks aktualisiert werden sollen</param> /// <param name="index">Der ins Zentrum zu setzende Chunk</param> /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param> private void InternalSetCenter(CancellationToken token, Index2 index, Action<bool> successCallback) { if (Planet == null) { successCallback?.Invoke(true); return; } List<Index2> requiredChunkColumns = new List<Index2>(); for (int x = -range; x <= range; x++) { for (int y = -range; y <= range; y++) { Index2 local = new Index2(index.X + x, index.Y + y); local.NormalizeXY(Planet.Size); requiredChunkColumns.Add(local); } } // Erste Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } foreach (var chunkColumnIndex in requiredChunkColumns .OrderBy(c => index.ShortestDistanceXY(c, new Index2(Planet.Size)) .LengthSquared())) { int localX = chunkColumnIndex.X & mask; int localY = chunkColumnIndex.Y & mask; int flatIndex = FlatIndex(localX, localY); IChunkColumn chunkColumn = chunkColumns[flatIndex]; // Alten Chunk entfernen, falls notwendig using (semaphore.Wait()) { if (chunkColumn != null && chunkColumn.Index != chunkColumnIndex) { //logger.Debug($"Remove Chunk: {chunkColumn.Index}, new: {chunkColumnIndex}"); globalCache.Release(chunkColumn.Index); chunkColumns[flatIndex] = null; chunkColumn = null; } } // Zweite Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } using (semaphore.Wait()) { // Neuen Chunk laden if (chunkColumn == null) { chunkColumn = globalCache.Subscribe(new Index2(chunkColumnIndex)); if (chunkColumn?.Index != chunkColumnIndex) logger.Error($"Loaded Chunk Index: {chunkColumn?.Index}, wanted: {chunkColumnIndex} "); if (chunkColumns[flatIndex] != null) logger.Error($"Chunk in Array!!: {flatIndex}, on index: {chunkColumns[flatIndex].Index} "); chunkColumns[flatIndex] = chunkColumn; if (chunkColumn == null) { successCallback?.Invoke(false); return; } } } // Dritte Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } } successCallback?.Invoke(true); }
/// <summary> /// Normalisiert den Wert von X und Y auf den angegebenen Grenzbereich. /// </summary> /// <param name="index">Der zu normalisierende Index2</param> /// <param name="size">3D Size</param> public static Index2 NormalizeXY(Index2 index, Index3 size) { index.NormalizeXY(size); return(index); }
/// <summary> /// Normalisiert den Wert von X und Y auf den angegebenen Grenzbereich. /// </summary> /// <param name="index">Der zu normalisierende Index2</param> /// <param name="size">3D Size</param> public static Index2 NormalizeXY(Index2 index,Index3 size) { index.NormalizeXY(size); return index; }
private void RenderToBackBuffer() { int offsetX = (int)(this.offsetX / Chunk.CHUNKSIZE_X), offsetY = (int)(this.offsetY / Chunk.CHUNKSIZE_Y); BitmapData bmpData = backBuffer.LockBits(new Rectangle(new Point(), backBuffer.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int[] emptyData = new int[Chunk.CHUNKSIZE_X * Chunk.CHUNKSIZE_Y]; unsafe { int* ptr = (int*)bmpData.Scan0; for (int y = offsetY ; y < offsetY + sizeY; y++) { for (int x = offsetX ; x < offsetX + sizeX; x++) { if ((y - offsetY) < 0 || (x - offsetX) < 0) continue; Index2 normalized = new Index2(x, y); normalized.NormalizeXY(Map.Planet.Size); int index = normalized.Y * Map.Planet.Size.X + normalized.X; int offset = (y - offsetY) * Chunk.CHUNKSIZE_Y * backBuffer.Width + (x - offsetX) * Chunk.CHUNKSIZE_X; if (Map.Chunks[index] == null) { CopyRegion(backBuffer, ptr, offset, Chunk.CHUNKSIZE_X, Chunk.CHUNKSIZE_Y, emptyData); continue; } int[] bmp = Map.Chunks[index].GetBitmapData(); if (bmp == null) continue; CopyRegion(backBuffer, ptr, offset, Chunk.CHUNKSIZE_X, Chunk.CHUNKSIZE_Y, bmp); //Chunk.CHUNKSIZE_X, Chunk.CHUNKSIZE_Y index++; } } } backBuffer.UnlockBits(bmpData); }
void LoadViewRange(int offsetX, int offsetY, int sizeX, int sizeY) { for (int y = offsetY; y < offsetY + sizeY; y++) { for (int x = offsetX; x < offsetX + sizeX; x++) { Index2 normalized = new Index2(x, y); normalized.NormalizeXY(Map.Planet.Size); int index = normalized.Y * Map.Planet.Size.X + normalized.X; if (Map.Chunks[index] != null) continue; IChunk[] tempChunks = Map.Generator.GenerateChunk (BlockDefinitionManager.GetBlockDefinitions(), Map.Planet, normalized); Map.Chunks[index] = new Chunk2D(tempChunks); if (!IsHandleCreated) return; } } }
/// <summary> /// Interne Methode, in der der zentrale Chunk gesetzt wird. Die Chunks um den Zentrumschunk werden auch nachgeladen falls nötig /// </summary> /// <param name="token">Token, um zu prüfen, ob die aktualisierung abgeborchen werden soll</param> /// <param name="planet">Der Planet, auf dem die Chunks aktualisiert werden sollen</param> /// <param name="index">Der ins Zentrum zu setzende Chunk</param> /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param> private void InternalSetCenter(CancellationToken token, IPlanet planet, Index2 index, Action<bool> successCallback) { // Planet resetten falls notwendig if (this.planet != planet) InitializePlanet(planet); if (planet == null) { if (successCallback != null) successCallback(true); return; } List<Index2> requiredChunkColumns = new List<Index2>(); for (int x = -range; x <= range; x++) { for (int y = -range; y <= range; y++) { Index2 local = new Index2(index.X + x, index.Y + y); local.NormalizeXY(planet.Size); requiredChunkColumns.Add(local); } } // Erste Abbruchmöglichkeit if (token.IsCancellationRequested) { if (successCallback != null) successCallback(false); return; } foreach (var chunkColumnIndex in requiredChunkColumns.OrderBy(c => index.ShortestDistanceXY(c, new Index2(planet.Size)).LengthSquared())) { int localX = chunkColumnIndex.X & mask; int localY = chunkColumnIndex.Y & mask; int flatIndex = FlatIndex(localX, localY); IChunkColumn chunkColumn = chunkColumns[flatIndex]; // Alten Chunk entfernen, falls notwendig if (chunkColumn != null && chunkColumn.Index != chunkColumnIndex) { globalCache.Release(planet.Id, chunkColumn.Index); chunkColumns[flatIndex] = null; chunkColumn = null; } // Zweite Abbruchmöglichkeit if (token.IsCancellationRequested) { if (successCallback != null) successCallback(false); return; } // Neuen Chunk laden if (chunkColumn == null) { chunkColumn = globalCache.Subscribe(planet.Id, new Index2(chunkColumnIndex)); chunkColumns[flatIndex] = chunkColumn; } // Dritte Abbruchmöglichkeit if (token.IsCancellationRequested) { if (successCallback != null) successCallback(false); return; } } if (successCallback != null) successCallback(true); }