Beispiel #1
0
        public void DrawTiles(Graphics g, Point p, Rectangle terrainRectangle, Func <Point, int> terrain)
        {
            // Calculate and clip screen coordinates of terrain
            var sx1 = Math.Max(p.X + terrainRectangle.Left * TileSize, (int)g.ClipBounds.Left);
            var sy1 = Math.Max(p.Y + terrainRectangle.Top * TileSize, (int)g.ClipBounds.Top);
            var sx2 = Math.Min(p.X + terrainRectangle.Right * TileSize, (int)g.ClipBounds.Right);
            var sy2 = Math.Min(p.Y + terrainRectangle.Bottom * TileSize, (int)g.ClipBounds.Bottom);

            if (sx1 >= sx2 || sy1 >= sy2)
            {
                return;
            }

            // Calculate clipped terrain coordinates
            var tx1 = (sx1 - p.X) / TileSize;
            var ty1 = (sy1 - p.Y) / TileSize;
            var tx2 = (sx2 - p.X) / TileSize;
            var ty2 = (sy2 - p.Y) / TileSize;

            // Prepare pixmap; pixmap covers screen coordinates (sx1,sy1) to (sx2,sy2)
            if (_Pixmap == null || _Pixmap.Width != sx2 - sx1 || _Pixmap.Height != sy2 - sy1)
            {
                _Pixmap = new Pixmap(sx2 - sx1, sy2 - sy1);
            }

            // Prepare layers pixmaps
            if (_PixmapsTileSize != TileSize)
            {
                foreach (var layer in _Layers)
                {
                    layer.CreatePixmaps(TileSize);
                }
                _PixmapsTileSize = TileSize;
            }

            // Prepare terrain cache
            int originX = tx1 - 1;
            int originY = ty1 - 1;
            int sizeX   = tx2 - tx1 + 2 + 2;
            int sizeY   = ty2 - ty1 + 2 + 2;

            if (_Terrain == null || _Terrain.Length != sizeX * sizeY)
            {
                _Terrain = new int[sizeX * sizeY];
            }
            for (int y = 0; y < sizeY; ++y)
            {
                for (int x = 0; x < sizeX; ++x)
                {
                    _Terrain[x + y * sizeX] = terrain(new Point(x + originX, y + originY));
                }
            }

            // Draw all layers
            foreach (var layer in _Layers)
            {
                if (layer.Layout == LayerLayout.Corners)
                {
                    // For all terrain locations to draw
                    Parallel.For(ty1, ty2 + 2, ty =>
                                 // for (int ty = ty1; ty < ty2 + 2; ++ty)
                    {
                        for (int tx = tx1; tx < tx2 + 2; ++tx)
                        {
                            // Get pixmap position of terrain location
                            int px = tx * TileSize + p.X - sx1 - TileSize / 2;
                            int py = ty * TileSize + p.Y - sy1 - TileSize / 2;

                            // Get layers masks of surrounding terrain locations (corners)
                            int cmask1 = _Terrain[(tx - originX - 1) + (ty - originY - 1) * sizeX];
                            int cmask2 = _Terrain[(tx - originX) + (ty - originY - 1) * sizeX];
                            int cmask3 = _Terrain[(tx - originX - 1) + (ty - originY) * sizeX];
                            int cmask4 = _Terrain[(tx - originX) + (ty - originY) * sizeX];

                            // Prepare seed for selecting random variations of tiles
                            int seed = tx | (ty << 16);

                            // Draw tile
                            int code = 0;
                            if ((cmask1 & layer.ConnectionsMask) != 0)
                            {
                                code += 1;
                            }
                            if ((cmask2 & layer.ConnectionsMask) != 0)
                            {
                                code += 2;
                            }
                            if ((cmask3 & layer.ConnectionsMask) != 0)
                            {
                                code += 4;
                            }
                            if ((cmask4 & layer.ConnectionsMask) != 0)
                            {
                                code += 8;
                            }
                            if (code != 0)
                            {
                                Point coords = layer.GetTileCoords(code, seed);
                                var srcRect  = new Rectangle(TileSize * coords.X, TileSize * coords.Y, TileSize, TileSize);
                                if (layer.WrapPixmap != null)
                                {
                                    Pixmap.Draw2(layer.TilesPixmap, layer.WrapPixmap, _Pixmap, srcRect, new Point(tx * TileSize, ty * TileSize), new Point(px, py));
                                }
                                else
                                {
                                    Pixmap.Draw(layer.TilesPixmap, _Pixmap, srcRect, px, py);
                                }
                            }
                        }
                    });
                }
                else
                {
                    // For all terrain locations to draw
                    Parallel.For(ty1, ty2 + 1, ty =>
                                 //for (int ty = ty1; ty < ty2 + 1; ++ty)
                    {
                        for (int tx = tx1; tx < tx2 + 1; ++tx)
                        {
                            // If location contains this layer
                            int mask = terrain(new Point(tx, ty));
                            if ((mask & layer.Mask) != 0)
                            {
                                // Get pixmap position of terrain location
                                int px = tx * TileSize + p.X - sx1;
                                int py = ty * TileSize + p.Y - sy1;

                                // Get layers masks of surrounding terrain locations (sides)
                                //int lmask = terrain(new Point(tx - 1, ty));
                                //int umask = terrain(new Point(tx, ty - 1));
                                //int rmask = terrain(new Point(tx + 1, ty));
                                //int dmask = terrain(new Point(tx, ty + 1));
                                int lmask = _Terrain[(tx - originX - 1) + (ty - originY) * sizeX];
                                int umask = _Terrain[(tx - originX) + (ty - originY - 1) * sizeX];
                                int rmask = _Terrain[(tx - originX + 1) + (ty - originY) * sizeX];
                                int dmask = _Terrain[(tx - originX) + (ty - originY + 1) * sizeX];

                                // Prepare seed for selecting random variations of tiles
                                int seed = tx | (ty << 16);

                                // Draw tile
                                int code = 0;
                                if ((lmask & layer.ConnectionsMask) != 0)
                                {
                                    code += 1;
                                }
                                if ((umask & layer.ConnectionsMask) != 0)
                                {
                                    code += 2;
                                }
                                if ((rmask & layer.ConnectionsMask) != 0)
                                {
                                    code += 4;
                                }
                                if ((dmask & layer.ConnectionsMask) != 0)
                                {
                                    code += 8;
                                }
                                Point coords = layer.GetTileCoords(code, seed);
                                var srcRect  = new Rectangle(TileSize * coords.X, TileSize * coords.Y, TileSize, TileSize);
                                if (layer.WrapPixmap != null)
                                {
                                    Pixmap.Draw2(layer.TilesPixmap, layer.WrapPixmap, _Pixmap, srcRect, new Point(tx * TileSize, ty * TileSize), new Point(px, py));
                                }
                                else
                                {
                                    Pixmap.Draw(layer.TilesPixmap, _Pixmap, srcRect, px, py);
                                }
                            }
                        }
                    });
                }
            }

            // Copy pixmap to graphics
            g.SmoothingMode   = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
            g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
            g.DrawImageUnscaled(_Pixmap.Bitmap, new Point(sx1, sy1));
        }