/// <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 }