/// <summary>
        ///  Paint sprites on the given surface.  This method is the meat
        ///  of the graphics engine.  Normally, creatures are painted to
        ///  the work surface using this method.  To increase performance plants
        ///  are rendered to the background surface only once every 10 frames.
        ///  Lots of work happening in this function so either read through the
        ///  code or examine the Terrarium Graphics Engine whitepaper for more
        ///  information.
        /// </summary>
        /// <param name="surf">The surface to render to.</param>
        /// <param name="PlantsOnly">True to render plants, false to render animals.</param>
        private void PaintSprites(IGraphicsSurface surf, bool PlantsOnly)
        {
            #if TRACE
            Profiler.Start("TerrariumDirectDrawGameView.PaintSprites()");
            #endif
            if (wv == null)
            {
                return;
            }

            if (tfm.Count > 100)
            {
                tfm.Clear();
            }

            var TeleporterZIndices = TeleporterZIndex();
            var lastTeleporterZIndex = 0;

            foreach (OrganismState orgState in wv.State.ZOrderedOrganisms)
            {
                if (orgState.RenderInfo != null)
                {
                    var tsSprite = (TerrariumSprite) orgState.RenderInfo;

                    if ((PlantsOnly && !(orgState.Species is PlantSpecies)) ||
                        (!PlantsOnly && orgState.Species is PlantSpecies))
                    {
                        continue;
                    }

                    if (orgState.Species is AnimalSpecies)
                    {
                        tsSprite.AdvanceFrame();
                        orgState.RenderInfo = tsSprite;
                    }

                    if (!videomemory && skipframe)
                    {
                        continue;
                    }

                    TerrariumSpriteSurface workTss = null;

                    if (workTss == null && tsSprite.SpriteKey != null)
                    {
                        workTss = tsm[tsSprite.SpriteKey, orgState.Radius, (orgState.Species is AnimalSpecies)];
                    }

                    if (workTss == null && tsSprite.SkinFamily != null)
                    {
                        workTss = tsm[tsSprite.SkinFamily, orgState.Radius, (orgState.Species is AnimalSpecies)];
                    }

                    if (workTss == null)
                    {
                        if (orgState.Species is AnimalSpecies)
                        {
                            workTss = tsm["ant", orgState.Radius, (orgState.Species is AnimalSpecies)];
                        }
                        else
                        {
                            workTss = tsm["plant", orgState.Radius, (orgState.Species is AnimalSpecies)];
                        }
                    }

                    if (workTss != null)
                    {
                        var direction = orgState.ActualDirection;
                        var radius = orgState.Radius;
                        var framedir = 1;
                        var workSurface = workTss.GetClosestSurface((radius*2));
                        radius = workSurface.FrameWidth;

                        if (direction >= 68 && direction < 113)
                        {
                            framedir = 1;
                        }
                        else if (direction >= 113 && direction < 158)
                        {
                            framedir = 2;
                        }
                        else if (direction >= 158 && direction < 203)
                        {
                            framedir = 3;
                        }
                        else if (direction >= 203 && direction < 248)
                        {
                            framedir = 4;
                        }
                        else if (direction >= 248 && direction < 293)
                        {
                            framedir = 5;
                        }
                        else if (direction >= 293 && direction < 338)
                        {
                            framedir = 6;
                        }
                        else if (direction >= 338 && direction < 23)
                        {
                            framedir = 7;
                        }
                        else
                        {
                            framedir = 8;
                        }

                        var dest = new Rectangle((int) tsSprite.XPosition - (_viewsize.Left + (radius >> 1)),
                                                 (int) tsSprite.YPosition - (_viewsize.Top + (radius >> 1)),
                                                 (int) tsSprite.XPosition - (_viewsize.Left + (radius >> 1)) + radius,
                                                 (int) tsSprite.YPosition - (_viewsize.Top + (radius >> 1)) + radius);

                        if (updateMiniMap)
                        {
                            var miniMapX = (int) (tsSprite.XPosition*miniMap.Width)/_actualsize.Right;
                            miniMapX = (miniMapX > (miniMap.Width - 1)) ? (miniMap.Width - 1) : miniMapX;
                            var miniMapY = (int) (tsSprite.YPosition*miniMap.Height)/_actualsize.Bottom;
                            miniMapY = (miniMapY > (miniMap.Height - 1)) ? (miniMap.Height - 1) : miniMapY;

                            var brushColor = Color.Fuchsia;

                            if (orgState.Species.GetType() == typeof (PlantSpecies))
                            {
                                brushColor = Color.Lime;
                            }
                            else if (orgState.IsAlive == false)
                            {
                                brushColor = Color.Black;
                            }
                            else
                            {
                                var orgSpecies = (Species) orgState.Species;
                                if (orgSpecies.MarkingColor == KnownColor.Green ||
                                    orgSpecies.MarkingColor == KnownColor.Black)
                                {
                                    brushColor = Color.Red;
                                }
                                else
                                {
                                    brushColor = Color.FromKnownColor(orgSpecies.MarkingColor);
                                }
                            }

                            Brush orgBrush = new SolidBrush(brushColor);

                            var miniMapGraphics = Graphics.FromImage(miniMap);
                            miniMapGraphics.FillRectangle(orgBrush, miniMapX, miniMapY, 12, 12);
                            miniMapGraphics.Dispose();
                            orgBrush.Dispose();

                            //this.miniMap.SetPixel(
                            //    miniMapX,
                            //    miniMapY,
                            //    (orgState.Species is PlantSpecies) ? Color.Green : (!orgState.IsAlive) ? Color.Black : (((Species) orgState.Species).MarkingColor == KnownColor.Green || ((Species) orgState.Species).MarkingColor == KnownColor.Black) ? Color.Red : Color.FromKnownColor(((Species) orgState.Species).MarkingColor));
                        }

                        DirectDrawClippedRect ddClipRect;
                        if (orgState.Species is PlantSpecies)
                        {
                            ddClipRect = workSurface.GrabSprite((int) tsSprite.CurFrame, 0, dest, _clipRect);
                        }
                        else
                        {
                            if (tsSprite.PreviousAction == DisplayAction.NoAction ||
                                tsSprite.PreviousAction == DisplayAction.Reproduced ||
                                tsSprite.PreviousAction == DisplayAction.Teleported ||
                                tsSprite.PreviousAction == DisplayAction.Dead)
                            {
                                if (tsSprite.PreviousAction == DisplayAction.Dead)
                                {
                                    ddClipRect = workSurface.GrabSprite(
                                        9,
                                        ((int) DisplayAction.Died) + framedir,
                                        dest,
                                        _clipRect);
                                }
                                else
                                {
                                    ddClipRect = workSurface.GrabSprite(0, ((int) DisplayAction.Moved) + framedir, dest,
                                                                        _clipRect);
                                }
                            }
                            else
                            {
                                ddClipRect = workSurface.GrabSprite((int) tsSprite.CurFrame,
                                                                    ((int) tsSprite.PreviousAction) + framedir, dest,
                                                                    _clipRect);
                            }
                        }

                        if (!ddClipRect.Invisible)
                        {
                            if (!PlantsOnly)
                            {
                                RenderTeleporter(lastTeleporterZIndex, (int) tsSprite.YPosition);
                                lastTeleporterZIndex = (int) tsSprite.YPosition;
                            }

                            surf.BltFast(ddClipRect.Destination.Left, ddClipRect.Destination.Top, workSurface.SpriteSurface, ref ddClipRect.Source, BltFastFlags.SrcColorKey);

                            if (drawtext && !PlantsOnly)
                            {
                                var textSurface = tfm[((Species) orgState.Species).Name];
                                if (textSurface != null && textSurface.Surface != null)
                                {
                                    surf.BltFast(ddClipRect.Destination.Left, ddClipRect.Destination.Top - 14, textSurface,
                                                 ref TerrariumTextSurfaceManager.StandardFontRect, BltFastFlags.SrcColorKey);
                                }
                            }

                            if (!ddClipRect.ClipLeft &&
                                !ddClipRect.ClipRight &&
                                !ddClipRect.ClipTop &&
                                !ddClipRect.ClipBottom)
                            {
                                if (drawDestinationLines)
                                {
                                    if (orgState.CurrentMoveToAction != null)
                                    {
                                        var start = orgState.Position;
                                        var end = orgState.CurrentMoveToAction.MovementVector.Destination;
                                        ((DirectDrawSurface)surf).Surface.SetForeColor(0);
                                        ((DirectDrawSurface)surf).Surface.DrawLine(start.X - _viewsize.Left, start.Y - _viewsize.Top,
                                                             end.X - _viewsize.Left, end.Y - _viewsize.Top);
                                    }
                                }

                                if (drawBoundingBox)
                                {
                                    var boundingBox = GetBoundsOfState(orgState);
                                    ((DirectDrawSurface)surf).Surface.SetForeColor(0);
                                    ((DirectDrawSurface)surf).Surface.DrawBox(
                                        boundingBox.Left - _viewsize.Left,
                                        boundingBox.Top - _viewsize.Top,
                                        (boundingBox.Right + 1) - _viewsize.Left,
                                        (boundingBox.Bottom + 1) - _viewsize.Top
                                        );
                                }

                                if (tsSprite.Selected)
                                {
                                    ((DirectDrawSurface)surf).Surface.SetForeColor(0);
                                    ((DirectDrawSurface)surf).Surface.DrawBox(ddClipRect.Destination.Left, ddClipRect.Destination.Top,
                                                        ddClipRect.Destination.Right, ddClipRect.Destination.Bottom);

                                    // red  Maybe we want some cool graphic here though
                                    var lineheight =
                                        (int)
                                        ((ddClipRect.Destination.Bottom - ddClipRect.Destination.Top)*
                                         orgState.PercentEnergy);
                                    ((DirectDrawSurface)surf).Surface.SetForeColor(63488);
                                    ((DirectDrawSurface)surf).Surface.DrawLine(ddClipRect.Destination.Left - 1, ddClipRect.Destination.Top,
                                                         ddClipRect.Destination.Left - 1,
                                                         ddClipRect.Destination.Top + lineheight);

                                    //green  Maybe we want some cool graphic here though (or an actual bar?)
                                    lineheight =
                                        (int)
                                        ((ddClipRect.Destination.Bottom - ddClipRect.Destination.Top)*
                                         orgState.PercentInjured);
                                    ((DirectDrawSurface)surf).Surface.SetForeColor(2016);
                                    ((DirectDrawSurface)surf).Surface.DrawLine(ddClipRect.Destination.Right + 1, ddClipRect.Destination.Top,
                                                         ddClipRect.Destination.Right + 1,
                                                         ddClipRect.Destination.Top + lineheight);
                                }
                            }
                        }
                    }
                }
            }

            RenderTeleporter(lastTeleporterZIndex, _actualsize.Bottom);

            #if TRACE
            Profiler.End("TerrariumDirectDrawGameView.PaintSprites()");
            #endif
        }